From 1d03db80d5038fcd5fc824fa6ba358218244a561 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Wed, 22 Apr 2009 02:41:38 +0000 Subject: [PATCH 001/114] branch from 2.5 for aligorith From ab3339f3801dcaedff8d4758c40c612cc65e86c9 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sun, 3 May 2009 11:46:57 +0000 Subject: [PATCH 002/114] NLA SoC: Initial commit of changes for the way NLA is evaluated * Recoded the flags for NLA-Strips to take into account the new design directions * Modified parts of the evaluation pipeline to reflect this --- source/blender/blenkernel/intern/action.c | 32 +-- source/blender/blenkernel/intern/anim_sys.c | 212 ++++++++++++++------ source/blender/makesdna/DNA_anim_types.h | 122 +++++------ 3 files changed, 220 insertions(+), 146 deletions(-) diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index d54bc749b71..f2e3583c87b 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -717,45 +717,25 @@ static bActionStrip *get_active_strip(Object *ob) return NULL; } -/* non clipped mapping of strip */ -static float get_actionstrip_frame(bActionStrip *strip, float cframe, int invert) -{ - float length, actlength, repeat, scale; - - if (strip->repeat == 0.0f) strip->repeat = 1.0f; - repeat = (strip->flag & ACTSTRIP_USESTRIDE) ? (1.0f) : (strip->repeat); - - if (strip->scale == 0.0f) strip->scale= 1.0f; - scale = (float)fabs(strip->scale); /* scale must be positive (for now) */ - - actlength = strip->actend-strip->actstart; - if (actlength == 0.0f) actlength = 1.0f; - length = repeat * scale * actlength; - - /* invert = convert action-strip time to global time */ - if (invert) - return length*(cframe - strip->actstart)/(repeat*actlength) + strip->start; - else - return repeat*actlength*(cframe - strip->start)/length + strip->actstart; -} - /* if the conditions match, it converts current time to strip time */ +// TODO: change this adt float get_action_frame(Object *ob, float cframe) { bActionStrip *strip= get_active_strip(ob); - if(strip) - return get_actionstrip_frame(strip, cframe, 0); + //if(strip) + // return get_actionstrip_frame(strip, cframe, 0); return cframe; } /* inverted, strip time to current time */ +// TODO: change this to adt float get_action_frame_inv(Object *ob, float cframe) { bActionStrip *strip= get_active_strip(ob); - if(strip) - return get_actionstrip_frame(strip, cframe, 1); + //if(strip) + // return get_actionstrip_frame(strip, cframe, 1); return cframe; } diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 30dcb383ef6..2840e3f5d45 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -5,6 +5,7 @@ #include #include #include +#include #include "MEM_guardedalloc.h" @@ -544,19 +545,17 @@ typedef struct NlaEvalStrip { struct NlaEvalStrip *next, *prev; NlaTrack *track; /* track that this strip belongs to */ - NlaStrip *strip; /* strip that's being used */ - NlaStrip *sblend; /* strip that's being blended towards (if applicable) */ + NlaStrip *strip; /* strip that's being used */ short track_index; /* the index of the track within the list */ short strip_mode; /* which end of the strip are we looking at */ } NlaEvalStrip; -/* bNlaEvalStrip->strip_mode */ +/* NlaEvalStrip->strip_mode */ enum { NES_TIME_BEFORE = -1, NES_TIME_WITHIN, NES_TIME_AFTER, - NES_TIME_AFTER_BLEND } eNlaEvalStrip_StripMode; @@ -565,8 +564,9 @@ enum { typedef struct NlaEvalChannel { struct NlaEvalChannel *next, *prev; - char *path; /* ready-to-use path (i.e. remapped already) */ - int array_index; /* if applicable... */ + PointerRNA *ptr; /* pointer to struct containing property to use */ + PropertyRNA *prop; /* RNA-property type to use (should be in the struct given) */ + int index; /* array index (where applicable) */ float value; /* value of this channel */ } NlaEvalChannel; @@ -574,24 +574,98 @@ typedef struct NlaEvalChannel { /* ---------------------- */ -/* evaluate the F-Curves controlling settings for the NLA-strips (currently, not relinkable) */ -static void nlastrip_evaluate_fcurves (NlaStrip *strip, float ctime) +/* non clipped mapping for strip-time <-> global time + * invert = convert action-strip time to global time + */ +static float nlastrip_get_frame (NlaStrip *strip, float cframe, short invert) { - //PointerRNA actstrip_ptr; - //FCurve *fcu; + float length, actlength, repeat, scale; - /* create RNA-pointer needed to set values */ - //RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &actstrip_ptr); + /* get number of repeats */ + if (strip->repeat == 0.0f) strip->repeat = 1.0f; + repeat = strip->repeat; - /* execute these settings as per normal */ - //animsys_evaluate_fcurves(&actstrip_ptr, &strip->fcurves, NULL, ctime); + /* scaling */ + if (strip->scale == 0.0f) strip->scale= 1.0f; + scale = (float)fabs(strip->scale); /* scale must be positive - we've got a special flag for reversing */ + + /* length of referenced action */ + actlength = strip->actend-strip->actstart; + if (actlength == 0.0f) actlength = 1.0f; + + /* length of strip */ + length = repeat * scale * actlength; + + /* reversed = play strip backwards */ + if (strip->flag & NLASTRIP_FLAG_REVERSE) { + // FIXME: verify these + /* invert = convert action-strip time to global time */ + if (invert) + return length*(strip->actend - cframe)/(repeat*actlength) + strip->start; + else + return strip->actend - repeat*actlength*(cframe - strip->start)/length; + } + else { + /* invert = convert action-strip time to global time */ + if (invert) + return length*(cframe - strip->actstart)/(repeat*actlength) + strip->start; + else + return repeat*actlength*(cframe - strip->start)/length + strip->actstart; + } +} + +/* calculate influence of strip based for given frame based on blendin/out values */ +static float nlastrip_get_influence (NlaStrip *strip, float cframe) +{ + /* sanity checks - normalise the blendin/out values? */ + strip->blendin= (float)fabs(strip->blendin); + strip->blendout= (float)fabs(strip->blendout); + + /* result depends on where frame is in respect to blendin/out values */ + // TODO: are the fabs() tests needed here? + if (IS_EQ(strip->blendin, 0)==0 && (cframe <= (strip->start + strip->blendin))) { + /* there is some blend-in */ + return (float)fabs(cframe - strip->start) / (strip->blendin); + } + else if (IS_EQ(strip->blendout, 0)==0 && (cframe >= (strip->end - strip->blendout))) { + /* there is some blend-out */ + return (float)fabs(strip->end - cframe) / (strip->blendout); + } + else { + /* in the middle of the strip, we should be full strength */ + return 1.0f; + } +} + +/* evaluate the evaluation time and influence for the strip, storing the results in the strip */ +void nlastrip_evaluate_controls (NlaStrip *strip, float cframe) +{ + /* firstly, analytically generate values for influence and time (if applicable) */ + if ((strip->flag & NLASTRIP_FLAG_USR_TIME) == 0) + strip->strip_time= nlastrip_get_frame(strip, cframe, 1); /* last arg '1' means current time to 'strip'/action time */ + if ((strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) == 0) + strip->influence= nlastrip_get_influence(strip, cframe); + + /* now strip's evaluate F-Curves for these settings (if applicable) */ + if (strip->fcurves.first) { +#if 0 + PointerRNA strip_ptr; + FCurve *fcu; + + /* create RNA-pointer needed to set values */ + RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr); + + /* execute these settings as per normal */ + animsys_evaluate_fcurves(&actstrip_ptr, &strip->fcurves, NULL, ctime); +#endif + } } -/* gets the strip active at the current time for a track */ +/* gets the strip active at the current time for a track for evaluation purposes */ static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index, float ctime) { - NlaStrip *strip, *astrip=NULL, *bstrip=NULL; + NlaStrip *strip, *estrip=NULL; NlaEvalStrip *nes; short side= 0; @@ -601,71 +675,91 @@ static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index /* loop over strips, checking if they fall within the range */ for (strip= nlt->strips.first; strip; strip= strip->next) { - /* only consider if: - * - current time occurs within strip's extents - * - current time occurs before strip (if it is the first) - * - current time occurs after strip (if hold is on) - * - current time occurs between strips (1st of those isn't holding) - blend! - */ + /* check if current time occurs within this strip */ if (IN_RANGE(ctime, strip->start, strip->end)) { - astrip= strip; + /* this strip is active, so try to use it */ + estrip= strip; side= NES_TIME_WITHIN; break; } - else if (ctime < strip->start) { + + /* if time occurred before current strip... */ + if (ctime < strip->start) { if (strip == nlt->strips.first) { - astrip= strip; + /* before first strip - only try to use it if it extends backwards in time too */ + if (strip->extendmode == NLASTRIP_EXTEND_HOLD) + estrip= strip; + + /* side is 'before' regardless of whether there's a useful strip */ side= NES_TIME_BEFORE; - break; } else { - astrip= strip->prev; + /* before next strip - previous strip has ended, but next hasn't begun, + * so blending mode depends on whether strip is being held or not... + * - only occurs when no transition strip added, otherwise the transition would have + * been picked up above... + */ + strip= strip->prev; - if (astrip->flag & NLASTRIP_HOLDLASTFRAME) { - side= NES_TIME_AFTER; - break; - } - else { - bstrip= strip; - side= NES_TIME_AFTER_BLEND; - break; - } + if (strip->extendmode != NLASTRIP_EXTEND_NOTHING) + estrip= strip; + side= NES_TIME_AFTER; } + break; + } + + /* if time occurred after current strip... */ + if (ctime > strip->end) { + /* only if this is the last strip should we do anything, and only if that is being held */ + if (strip == nlt->strips.last) { + if (strip->extendmode != NLASTRIP_EXTEND_NOTHING) + estrip= strip; + + side= NES_TIME_AFTER; + break; + } + + /* otherwise, skip... as the 'before' case will catch it more elegantly! */ } } - /* check if strip has been found (and whether it has data worth considering) */ - if (ELEM(NULL, astrip, astrip->act)) - return; - if (astrip->flag & NLASTRIP_MUTE) + /* check if a valid strip was found + * - must not be muted (i.e. will have contribution + */ + if ((estrip == NULL) || (estrip->flag & NLASTRIP_FLAG_MUTED)) return; - /* check if blending between strips */ - if (side == NES_TIME_AFTER_BLEND) { - /* blending between strips... so calculate influence+act_time of both */ - nlastrip_evaluate_fcurves(astrip, ctime); - nlastrip_evaluate_fcurves(bstrip, ctime); + /* evaluate strip's evaluation controls + * - skip if no influence (i.e. same effect as muting the strip) + * - negative influence is not supported yet... how would that be defined? + */ + // TODO: this sounds a bit hacky having a few isolated F-Curves stuck on some data it operates on... + nlastrip_evaluate_controls(estrip, ctime); + if (estrip->influence <= 0.0f) + return; - if ((astrip->influence <= 0.0f) && (bstrip->influence <= 0.0f)) - return; - } - else { - /* calculate/set the influence+act_time of this strip - don't consider if 0 influence */ - nlastrip_evaluate_fcurves(astrip, ctime); - - if (astrip->influence <= 0.0f) - return; + /* check if strip has valid data to evaluate */ + switch (estrip->type) { + case NLASTRIP_TYPE_CLIP: + /* clip must have some action to evaluate */ + if (estrip->act == NULL) + return; + break; + case NLASTRIP_TYPE_TRANSITION: + /* there must be strips to transition from and to (i.e. prev and next required) */ + // TODO: what happens about cross-track transitions? + if (ELEM(NULL, estrip->prev, estrip->next)) + return; + break; } - - /* allocate new eval-strip for this strip + add to stack */ + /* add to list of strips we need to evaluate */ nes= MEM_callocN(sizeof(NlaEvalStrip), "NlaEvalStrip"); nes->track= nlt; - nes->strip= astrip; - nes->sblend= bstrip; - nes->track_index= index; + nes->strip= estrip; nes->strip_mode= side; + nes->track_index= index; BLI_addtail(list, nes); } diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h index d015d703309..7ca3110912d 100644 --- a/source/blender/makesdna/DNA_anim_types.h +++ b/source/blender/makesdna/DNA_anim_types.h @@ -360,26 +360,13 @@ typedef struct AnimMapper { /* ************************************************ */ /* NLA - Non-Linear Animation */ -// TODO: the concepts here still need to be refined to solve any unresolved items - -/* NLA Modifiers ---------------------------------- */ - -/* These differ from F-Curve modifiers, as although F-Curve modifiers also operate on a - * per-channel basis too (in general), they are part of the animation data itself, which - * means that their effects are inherited by all of their users. In order to counteract this, - * the modifiers here should be used to provide variation to pre-created motions only. - */ /* NLA Strips ------------------------------------- */ /* NLA Strip (strip) * * A NLA Strip is a container for the reuse of Action data, defining parameters - * to control the remapping of the Action data to some destination. Actions being - * referenced by NLA-Strips SHOULD-NOT be editable, unless they were created in such - * a way that results in very little mapping distortion (i.e. for layered animation only, - * opposed to prebuilt 'blocks' which are quickly dumped into the NLA for crappymatic machima-type - * stuff) + * to control the remapping of the Action data to some destination. */ typedef struct NlaStrip { struct NlaStrip *next, *prev; @@ -387,58 +374,75 @@ typedef struct NlaStrip { bAction *act; /* Action that is referenced by this strip */ AnimMapper *remap; /* Remapping info this strip (for tweaking correspondance of action with context) */ - ListBase modifiers; /* NLA Modifiers */ - - ListBase fcurves; /* F-Curves for controlling this strip's influence and timing */ + ListBase fcurves; /* F-Curves for controlling this strip's influence and timing */ // TODO: move out? + ListBase modifiers; /* F-Curve modifiers to be applied to the entire strip's referenced F-Curves */ float influence; /* Influence of strip */ - float act_time; /* Current 'time' within action being used */ + float strip_time; /* Current 'time' within action being used (automatically evaluated, but can be overridden) */ float start, end; /* extents of the strip */ float actstart, actend; /* range of the action to use */ - float repeat; /* The number of times to repeat the action range (only when no F-Curves) */ - float scale; /* The amount the action range is scaled by (only when no F-Curves) */ + float repeat; /* The number of times to repeat the action range (only when no F-Curves) */ + float scale; /* The amount the action range is scaled by (only when no F-Curves) */ float blendin, blendout; /* strip blending length (only used when there are no F-Curves) */ - int blendmode; /* strip blending mode */ + short blendmode; /* strip blending mode (layer-based mixing) */ + short extendmode; /* strip extrapolation mode (time-based mixing) */ - int flag; /* settings */ - - // umm... old unused cruft? - int stride_axis; /* axis for stridebone stuff - 0=x, 1=y, 2=z */ - int pad; - - float actoffs; /* Offset within action, for cycles and striding (only set for ACT_USESTRIDE) */ - float stridelen; /* The stridelength (considered when flag & ACT_USESTRIDE) */ - - char stridechannel[32]; /* Instead of stridelen, it uses an action channel */ - char offs_bone[32]; /* if repeat, use this bone/channel for defining offset */ + short flag; /* settings */ + short type; /* type of NLA strip */ } NlaStrip; /* NLA Strip Blending Mode */ enum { - NLASTRIPMODE_BLEND = 0, - NLASTRIPMODE_ADD, - NLASTRIPMODE_SUBTRACT, -} eActStrip_Mode; + NLASTRIP_MODE_BLEND = 0, + NLASTRIP_MODE_ADD, + NLASTRIP_MODE_SUBTRACT, + NLASTRIP_MODE_MULTIPLY, +} eNlaStrip_Blend_Mode; + +/* NLA Strip Extrpolation Mode */ +enum { + /* extend before first frame if no previous strips in track, and always hold+extend last frame */ + NLASTRIP_EXTEND_HOLD = 0, + /* only hold+extend last frame */ + NLASTRIP_EXTEND_HOLD_FORWARD, + /* don't contribute at all */ + NLASTRIP_EXTEND_NOTHING, +} eNlaStrip_Extrapolate_Mode; /* NLA Strip Settings */ -// TODO: check on which of these are still useful... enum { - NLASTRIP_SELECT = (1<<0), - NLASTRIP_USESTRIDE = (1<<1), - NLASTRIP_BLENDTONEXT = (1<<2), /* Not implemented. Is not used anywhere */ - NLASTRIP_HOLDLASTFRAME = (1<<3), - NLASTRIP_ACTIVE = (1<<4), - NLASTRIP_LOCK_ACTION = (1<<5), - NLASTRIP_MUTE = (1<<6), - NLASTRIP_REVERSE = (1<<7), /* This has yet to be implemented. To indicate that a strip should be played backwards */ - NLASTRIP_CYCLIC_USEX = (1<<8), - NLASTRIP_CYCLIC_USEY = (1<<9), - NLASTRIP_CYCLIC_USEZ = (1<<10), - NLASTRIP_AUTO_BLENDS = (1<<11), - NLASTRIP_TWEAK = (1<<12), /* This strip is a tweaking strip (only set if owner track is a tweak track) */ -} eActionStrip_Flag; + /* UI selection flags */ + /* NLA strip is the active one in the track (also indicates if strip is being tweaked) */ + NLASTRIP_FLAG_ACTIVE = (1<<0), + /* NLA strip is selected for editing */ + NLASTRIP_FLAG_SELECT = (1<<1), +// NLASTRIP_FLAG_SELECT_L = (1<<2), // left handle selected +// NLASTRIP_FLAG_SELECT_R = (1<<3), // right handle selected + + /* controls driven by local F-Curves */ + /* strip influence is controlled by local F-Curve */ + NLASTRIP_FLAG_USR_INFLUENCE = (1<<5), + NLASTRIP_FLAG_USR_TIME = (1<<6), + + /* playback flags (may be overriden by F-Curves) */ + /* NLA strip blendin/out values are set automatically based on overlaps */ + NLASTRIP_FLAG_AUTO_BLENDS = (1<<10), + /* NLA strip is played back in reverse order */ + NLASTRIP_FLAG_REVERSE = (1<<11), + /* NLA strip is muted (i.e. doesn't contribute in any way) */ + // TODO: this overlaps a lot with the functionality in track + NLASTRIP_FLAG_MUTED = (1<<12), +} eNlaStrip_Flag; + +/* NLA Strip Type */ +enum { + /* 'clip' - references an Action */ + NLASTRIP_TYPE_CLIP = 0, + /* 'transition' - blends between the adjacent strips */ + NLASTRIP_TYPE_TRANSITION, +} eNlaStrip_Type; /* NLA Tracks ------------------------------------- */ @@ -457,14 +461,12 @@ typedef struct NlaTrack { int flag; /* settings for this track */ int index; /* index of the track in the stack (NOTE: not really useful, but we need a pad var anyways!) */ - char info[64]; /* short user-description of this track */ + char name[64]; /* short user-description of this track */ } NlaTrack; /* settings for track */ enum { - /* track is the one that settings can be modified on (doesn't indicate - * that it's for 'tweaking' though) - */ + /* track is the one that settings can be modified on, also indicates if track is being 'tweaked' */ NLATRACK_ACTIVE = (1<<0), /* track is selected in UI for relevant editing operations */ NLATRACK_SELECTED = (1<<1), @@ -474,10 +476,6 @@ enum { NLATRACK_SOLO = (1<<3), /* track's settings (and strips) cannot be edited (to guard against unwanted changes) */ NLATRACK_PROTECTED = (1<<4), - /* strip is the 'last' one that should be evaluated, as the active action - * is being used to tweak the animation of the strips up to here - */ - NLATRACK_TWEAK = (1<<5), } eNlaTrack_Flag; @@ -650,11 +648,13 @@ enum { ADT_NLA_SOLO_TRACK = (1<<0), /* don't use NLA */ ADT_NLA_EVAL_OFF = (1<<1), - /* don't execute drivers */ - ADT_DRIVERS_DISABLED = (1<<2), + /* NLA is being 'tweaked' (i.e. in EditMode) */ + ADT_NLA_EDIT_ON = (1<<2), /* drivers expanded in UI */ ADT_DRIVERS_COLLAPSED = (1<<10), + /* don't execute drivers */ + ADT_DRIVERS_DISABLED = (1<<11), } eAnimData_Flag; /* Animation Data recalculation settings (to be set by depsgraph) */ From e295cfd4d5e9adcd006cbab95f84eb93a73ea6bc Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 15 May 2009 13:23:03 +0000 Subject: [PATCH 003/114] NLA Branch: Setting up evaluation system for action strips * Refactored F-Curve Modifier stack evaluation into functions which can be reused for F-Curve Modifiers on NLA-Strips * Started setting up temporary accumulation buffer system for use when evaluating strips --- source/blender/blenkernel/BKE_fcurve.h | 6 +- source/blender/blenkernel/intern/anim_sys.c | 114 ++++++++++++-- source/blender/blenkernel/intern/fcurve.c | 156 ++++++++++++-------- 3 files changed, 203 insertions(+), 73 deletions(-) diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h index 9b8a2990fe5..7058b9d236a 100644 --- a/source/blender/blenkernel/BKE_fcurve.h +++ b/source/blender/blenkernel/BKE_fcurve.h @@ -108,11 +108,15 @@ struct FModifier *fcurve_add_modifier(struct FCurve *fcu, int type); void fcurve_copy_modifiers(ListBase *dst, ListBase *src); void fcurve_remove_modifier(struct FCurve *fcu, struct FModifier *fcm); void fcurve_free_modifiers(struct FCurve *fcu); -void fcurve_bake_modifiers(struct FCurve *fcu, int start, int end); struct FModifier *fcurve_find_active_modifier(struct FCurve *fcu); void fcurve_set_active_modifier(struct FCurve *fcu, struct FModifier *fcm); +float evaluate_time_fmodifiers(ListBase *modifiers, struct FCurve *fcu, float cvalue, float evaltime); +void evaluate_value_fmodifiers(ListBase *modifiers, struct FCurve *fcu, float *cvalue, float evaltime); + +void fcurve_bake_modifiers(struct FCurve *fcu, int start, int end); + /* ************** F-Curves API ******************** */ /* -------- Data Managemnt -------- */ diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 2840e3f5d45..5a4a2d91469 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -6,6 +6,7 @@ #include #include #include +#include #include "MEM_guardedalloc.h" @@ -564,7 +565,7 @@ enum { typedef struct NlaEvalChannel { struct NlaEvalChannel *next, *prev; - PointerRNA *ptr; /* pointer to struct containing property to use */ + PointerRNA ptr; /* pointer to struct containing property to use */ PropertyRNA *prop; /* RNA-property type to use (should be in the struct given) */ int index; /* array index (where applicable) */ @@ -638,13 +639,13 @@ static float nlastrip_get_influence (NlaStrip *strip, float cframe) } /* evaluate the evaluation time and influence for the strip, storing the results in the strip */ -void nlastrip_evaluate_controls (NlaStrip *strip, float cframe) +void nlastrip_evaluate_controls (NlaStrip *strip, float ctime) { /* firstly, analytically generate values for influence and time (if applicable) */ if ((strip->flag & NLASTRIP_FLAG_USR_TIME) == 0) - strip->strip_time= nlastrip_get_frame(strip, cframe, 1); /* last arg '1' means current time to 'strip'/action time */ + strip->strip_time= nlastrip_get_frame(strip, ctime, 1); /* last arg '1' means current time to 'strip'/action time */ if ((strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) == 0) - strip->influence= nlastrip_get_influence(strip, cframe); + strip->influence= nlastrip_get_influence(strip, ctime); /* now strip's evaluate F-Curves for these settings (if applicable) */ if (strip->fcurves.first) { @@ -766,13 +767,104 @@ static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index /* ---------------------- */ -/* evaluates the given evaluation strip */ -// FIXME: will we need the evaluation cache table set up to blend stuff in? -// TODO: only evaluate here, but flush in one go using the accumulated channels at end... -static void nlastrip_ctime_evaluate (ListBase *channels, NlaEvalStrip *nes, float ctime) +/* verify that an appropriate NlaEvalChannel for this F-Curve */ +static NlaEvalChannel *nlaevalchan_verify (PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes, FCurve *fcu, short *newChan) { - // 1. (in old code) was to extract 'IPO-channels' from actions - // 2. blend between the 'accumulated' data, and the new data + NlaEvalChannel *nec= NULL; + NlaStrip *strip= nes->strip; + PropertyRNA *prop; + PointerRNA new_ptr; + char *path = NULL; + short free_path=0; + + /* sanity checks */ + if (channels == NULL) + return NULL; + + /* get RNA pointer+property info from F-Curve for more convenient handling */ + /* get path, remapped as appropriate to work in its new environment */ + free_path= animsys_remap_path(strip->remap, fcu->rna_path, &path); + + /* get property to write to */ + if (RNA_path_resolve(ptr, path, &new_ptr, &prop) == 0) + return NULL; + /* only ok if animateable */ + else if (RNA_property_animateable(&new_ptr, prop) == 0) + return NULL; + + /* loop through existing channels, checking for a channel which affects the same property */ + for (nec= channels->first; nec; nec= nec->next) { + if ((nec->ptr.data == new_ptr.data) && (nec->prop == prop)) + return nec; + } + + /* allocate a new struct for this */ + nec= MEM_callocN(sizeof(NlaEvalChannel), "NlaEvalChannel"); + *newChan= 1; + BLI_addtail(channels, nec); + + nec->ptr= new_ptr; + nec->prop= prop; + nec->index= fcu->array_index; + + return nec; +} + +/* ---------------------- */ + +/* evaluate action-clip strip */ +static void nlastrip_evaluate_actionclip (PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes) +{ + NlaStrip *strip= nes->strip; + FCurve *fcu; + float evaltime; + + /* evaluate strip's modifiers which modify time to evaluate the base curves at */ + evaltime= evaluate_time_fmodifiers(&strip->modifiers, NULL, 0.0f, strip->strip_time); + + /* evaluate all the F-Curves in the action, saving the relevant pointers to data that will need to be used */ + for (fcu= strip->act->curves.first; fcu; fcu= fcu->next) { + NlaEvalChannel *nec; + float value = 0.0f; + short newChan = -1; + + /* check if this curve should be skipped */ + if (fcu->flag & (FCURVE_MUTED|FCURVE_DISABLED)) + continue; + + /* evaluate the F-Curve's value for the time given in the strip + * NOTE: we use the modified time here, since strip's F-Curve Modifiers are applied on top of this + */ + value= evaluate_fcurve(fcu, evaltime); + + /* apply strip's F-Curve Modifiers on this value + * NOTE: we apply the strip's original evaluation time not the modified one (as per standard F-Curve eval) + */ + evaluate_value_fmodifiers(&strip->modifiers, fcu, &value, strip->strip_time); + + + /* get an NLA evaluation channel to work with, and accumulate the evaluated value with the value(s) + * stored in this channel if it has been used already + */ + nec= nlaevalchan_verify(ptr, channels, nes, fcu, &newChan); + //if (nec) + // nlaevalchan_accumulate(ptr, nec, nes, newChan, value); + } +} + +/* evaluates the given evaluation strip */ +// TODO: only evaluate here, but flush in one go using the accumulated channels at end... +static void nlastrip_evaluate (PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes) +{ + /* actions to take depend on the type of strip */ + switch (nes->strip->type) { + case NLASTRIP_TYPE_CLIP: /* action-clip */ + nlastrip_evaluate_actionclip(ptr, channels, nes); + break; + case NLASTRIP_TYPE_TRANSITION: /* transition */ + // XXX code this... + break; + } } /* write the accumulated settings to */ @@ -807,7 +899,7 @@ static void animsys_evaluate_nla (PointerRNA *ptr, AnimData *adt, float ctime) /* 2. for each strip, evaluate then accumulate on top of existing channels, but don't set values yet */ for (nes= estrips.first; nes; nes= nes->next) - nlastrip_ctime_evaluate(&echannels, nes, ctime); + nlastrip_evaluate(ptr, &echannels, nes); /* 3. flush effects of accumulating channels in NLA to the actual data they affect */ nladata_flush_channels(ptr, &echannels); diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index cade555a07a..1a40911170e 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -2166,34 +2166,6 @@ void fcurve_free_modifiers (FCurve *fcu) } } -/* Bake modifiers for given F-Curve to curve sample data, in the frame range defined - * by start and end (inclusive). - */ -void fcurve_bake_modifiers (FCurve *fcu, int start, int end) -{ - ChannelDriver *driver; - - /* sanity checks */ - // TODO: make these tests report errors using reports not printf's - if ELEM(NULL, fcu, fcu->modifiers.first) { - printf("Error: No F-Curve with F-Curve Modifiers to Bake\n"); - return; - } - - /* temporarily, disable driver while we sample, so that they don't influence the outcome */ - driver= fcu->driver; - fcu->driver= NULL; - - /* bake the modifiers, by sampling the curve at each frame */ - fcurve_store_samples(fcu, NULL, start, end, fcurve_samplingcb_evalcurve); - - /* free the modifiers now */ - fcurve_free_modifiers(fcu); - - /* restore driver */ - fcu->driver= driver; -} - /* Find the active F-Curve Modifier */ FModifier *fcurve_find_active_modifier (FCurve *fcu) { @@ -2231,6 +2203,98 @@ void fcurve_set_active_modifier (FCurve *fcu, FModifier *fcm) fcm->flag |= FMODIFIER_FLAG_ACTIVE; } +/* Evaluation API --------------------------- */ + +/* evaluate time modifications imposed by some F-Curve Modifiers + * - this step acts as an optimisation to prevent the F-Curve stack being evaluated + * several times by modifiers requesting the time be modified, as the final result + * would have required using the modified time + * - modifiers only ever recieve the unmodified time, as subsequent modifiers should be + * working on the 'global' result of the modified curve, not some localised segment, + * so nevaltime gets set to whatever the last time-modifying modifier likes... + * - we start from the end of the stack, as only the last one matters for now + */ +float evaluate_time_fmodifiers (ListBase *modifiers, FCurve *fcu, float cvalue, float evaltime) +{ + FModifier *fcm; + float m_evaltime= evaltime; + + /* sanity checks */ + if ELEM(NULL, modifiers, modifiers->first) + return evaltime; + + /* find the first modifier from end of stack that modifies time, and calculate the time the modifier + * would calculate time at + */ + for (fcm= fcu->modifiers.last; fcm; fcm= fcm->prev) { + FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); + + /* only evaluate if there's a callback for this */ + // TODO: implement the 'influence' control feature... + if (fmi && fmi->evaluate_modifier_time) { + if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0) + m_evaltime= fmi->evaluate_modifier_time(fcu, fcm, cvalue, evaltime); + break; + } + } + + /* return the modified evaltime */ + return m_evaltime; +} + +/* Evalautes the given set of F-Curve Modifiers using the given data + * Should only be called after evaluate_time_fmodifiers() has been called... + */ +void evaluate_value_fmodifiers (ListBase *modifiers, FCurve *fcu, float *cvalue, float evaltime) +{ + FModifier *fcm; + + /* sanity checks */ + if ELEM(NULL, modifiers, modifiers->first) + return; + + /* evaluate modifiers */ + for (fcm= modifiers->first; fcm; fcm= fcm->next) { + FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); + + /* only evaluate if there's a callback for this */ + // TODO: implement the 'influence' control feature... + if (fmi && fmi->evaluate_modifier) { + if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0) + fmi->evaluate_modifier(fcu, fcm, cvalue, evaltime); + } + } +} + + +/* Bake modifiers for given F-Curve to curve sample data, in the frame range defined + * by start and end (inclusive). + */ +void fcurve_bake_modifiers (FCurve *fcu, int start, int end) +{ + ChannelDriver *driver; + + /* sanity checks */ + // TODO: make these tests report errors using reports not printf's + if ELEM(NULL, fcu, fcu->modifiers.first) { + printf("Error: No F-Curve with F-Curve Modifiers to Bake\n"); + return; + } + + /* temporarily, disable driver while we sample, so that they don't influence the outcome */ + driver= fcu->driver; + fcu->driver= NULL; + + /* bake the modifiers, by sampling the curve at each frame */ + fcurve_store_samples(fcu, NULL, start, end, fcurve_samplingcb_evalcurve); + + /* free the modifiers now */ + fcurve_free_modifiers(fcu); + + /* restore driver */ + fcu->driver= driver; +} + /* ***************************** F-Curve - Evaluation ********************************* */ /* Evaluate and return the value of the given F-Curve at the specified frame ("evaltime") @@ -2238,7 +2302,6 @@ void fcurve_set_active_modifier (FCurve *fcu, FModifier *fcm) */ float evaluate_fcurve (FCurve *fcu, float evaltime) { - FModifier *fcm; float cvalue= 0.0f; float devaltime; @@ -2251,28 +2314,8 @@ float evaluate_fcurve (FCurve *fcu, float evaltime) evaltime= cvalue= evaluate_driver(fcu->driver, evaltime); } - /* evaluate time modifications imposed by some F-Curve Modifiers - * - this step acts as an optimisation to prevent the F-Curve stack being evaluated - * several times by modifiers requesting the time be modified, as the final result - * would have required using the modified time - * - modifiers only ever recieve the unmodified time, as subsequent modifiers should be - * working on the 'global' result of the modified curve, not some localised segment, - * so nevaltime gets set to whatever the last time-modifying modifier likes... - * - we start from the end of the stack, as only the last one matters for now - */ - devaltime= evaltime; - - for (fcm= fcu->modifiers.last; fcm; fcm= fcm->prev) { - FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); - - /* only evaluate if there's a callback for this */ - // TODO: implement the 'influence' control feature... - if (fmi && fmi->evaluate_modifier_time) { - if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0) - devaltime= fmi->evaluate_modifier_time(fcu, fcm, cvalue, evaltime); - break; - } - } + /* evaluate modifiers which modify time to evaluate the base curve at */ + devaltime= evaluate_time_fmodifiers(&fcu->modifiers, fcu, cvalue, evaltime); /* evaluate curve-data * - 'devaltime' instead of 'evaltime', as this is the time that the last time-modifying @@ -2284,16 +2327,7 @@ float evaluate_fcurve (FCurve *fcu, float evaltime) cvalue= fcurve_eval_samples(fcu, fcu->fpt, devaltime); /* evaluate modifiers */ - for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next) { - FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); - - /* only evaluate if there's a callback for this */ - // TODO: implement the 'influence' control feature... - if (fmi && fmi->evaluate_modifier) { - if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0) - fmi->evaluate_modifier(fcu, fcm, &cvalue, evaltime); - } - } + evaluate_value_fmodifiers(&fcu->modifiers, fcu, &cvalue, evaltime); /* if curve can only have integral values, perform truncation (i.e. drop the decimal part) * here so that the curve can be sampled correctly From cebf6cb22deb930f5ec235e81c20072bf7154a83 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sat, 16 May 2009 01:00:41 +0000 Subject: [PATCH 004/114] NLA SoC: Code for basic evaluation of NLA strips done In theory, actions can now be evaluated in NLA, though in practice, we don't have an NLA Editor to create data to use this yet! Next up, transitions... Some notes: * Recoded the way the 'accumulation' methods work (i.e. blend, add, etc.), adding a few new ones. It should now be more obvious how these work. * Some assorted code cleanups done too (removing unneeded vars/args) --- source/blender/blenkernel/intern/anim_sys.c | 157 +++++++++++++++++--- 1 file changed, 135 insertions(+), 22 deletions(-) diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 5a4a2d91469..702da23ef47 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -735,8 +735,9 @@ static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index * - negative influence is not supported yet... how would that be defined? */ // TODO: this sounds a bit hacky having a few isolated F-Curves stuck on some data it operates on... + // TODO: should we clamp the time to only be on the endpoints of the strip? nlastrip_evaluate_controls(estrip, ctime); - if (estrip->influence <= 0.0f) + if (estrip->influence <= 0.0f) // XXX is it useful to invert the strip? return; /* check if strip has valid data to evaluate */ @@ -767,10 +768,36 @@ static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index /* ---------------------- */ -/* verify that an appropriate NlaEvalChannel for this F-Curve */ +/* find an NlaEvalChannel that matches the given criteria + * - ptr and prop are the RNA data to find a match for + */ +static NlaEvalChannel *nlaevalchan_find_match (ListBase *channels, PointerRNA *ptr, PropertyRNA *prop, int array_index) +{ + NlaEvalChannel *nec; + + /* sanity check */ + if (channels == NULL) + return NULL; + + /* loop through existing channels, checking for a channel which affects the same property */ + for (nec= channels->first; nec; nec= nec->next) { + /* - comparing the PointerRNA's is done by comparing the pointers + * to the actual struct the property resides in, since that all the + * other data stored in PointerRNA cannot allow us to definitively + * identify the data + */ + if ((nec->ptr.data == ptr->data) && (nec->prop == prop) && (nec->index == array_index)) + return nec; + } + + /* not found */ + return NULL; +} + +/* verify that an appropriate NlaEvalChannel for this F-Curve exists */ static NlaEvalChannel *nlaevalchan_verify (PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes, FCurve *fcu, short *newChan) { - NlaEvalChannel *nec= NULL; + NlaEvalChannel *nec; NlaStrip *strip= nes->strip; PropertyRNA *prop; PointerRNA new_ptr; @@ -785,31 +812,79 @@ static NlaEvalChannel *nlaevalchan_verify (PointerRNA *ptr, ListBase *channels, /* get path, remapped as appropriate to work in its new environment */ free_path= animsys_remap_path(strip->remap, fcu->rna_path, &path); - /* get property to write to */ - if (RNA_path_resolve(ptr, path, &new_ptr, &prop) == 0) + /* a valid property must be available, and it must be animateable */ + if (RNA_path_resolve(ptr, path, &new_ptr, &prop) == 0) { + if (G.f & G_DEBUG) printf("NLA Strip Eval: Cannot resolve path \n"); return NULL; + } /* only ok if animateable */ - else if (RNA_property_animateable(&new_ptr, prop) == 0) + else if (RNA_property_animateable(&new_ptr, prop) == 0) { + if (G.f & G_DEBUG) printf("NLA Strip Eval: Property not animateable \n"); return NULL; - - /* loop through existing channels, checking for a channel which affects the same property */ - for (nec= channels->first; nec; nec= nec->next) { - if ((nec->ptr.data == new_ptr.data) && (nec->prop == prop)) - return nec; } - /* allocate a new struct for this */ - nec= MEM_callocN(sizeof(NlaEvalChannel), "NlaEvalChannel"); - *newChan= 1; - BLI_addtail(channels, nec); + /* try to find a match */ + nec= nlaevalchan_find_match(channels, &new_ptr, prop, fcu->array_index); - nec->ptr= new_ptr; - nec->prop= prop; - nec->index= fcu->array_index; + /* allocate a new struct for this if none found */ + if (nec == NULL) { + nec= MEM_callocN(sizeof(NlaEvalChannel), "NlaEvalChannel"); + *newChan= 1; + BLI_addtail(channels, nec); + + nec->ptr= new_ptr; + nec->prop= prop; + nec->index= fcu->array_index; + } + /* we can now return */ return nec; } +/* accumulate (i.e. blend) the given value on to the channel it affects */ +static void nlaevalchan_accumulate (NlaEvalChannel *nec, NlaEvalStrip *nes, short newChan, float value) +{ + NlaStrip *strip= nes->strip; + float inf= strip->influence; + + /* if channel is new, just store value regardless of blending factors, etc. */ + if (newChan) { + nec->value= value; + return; + } + + /* premultiply the value by the weighting factor */ + if (IS_EQ(inf, 0)) return; + value *= inf; + + /* perform blending */ + switch (strip->blendmode) { + case NLASTRIP_MODE_ADD: + /* simply add the scaled value on to the stack */ + nec->value += value; + break; + + case NLASTRIP_MODE_SUBTRACT: + /* simply subtract the scaled value from the stack */ + nec->value -= value; + break; + + case NLASTRIP_MODE_MULTIPLY: + /* multiply the scaled value with the stack */ + nec->value *= value; + break; + + case NLASTRIP_MODE_BLEND: + default: // TODO: do we really want to blend by default? it seems more uses might prefer add... + /* do linear interpolation + * - the influence of the accumulated data (elsewhere, that is called dstweight) + * is 1 - influence, since the strip's influence is srcweight + */ + nec->value= nec->value * (1.0f - inf) + value; + break; + } +} + /* ---------------------- */ /* evaluate action-clip strip */ @@ -847,8 +922,8 @@ static void nlastrip_evaluate_actionclip (PointerRNA *ptr, ListBase *channels, N * stored in this channel if it has been used already */ nec= nlaevalchan_verify(ptr, channels, nes, fcu, &newChan); - //if (nec) - // nlaevalchan_accumulate(ptr, nec, nes, newChan, value); + if (nec) + nlaevalchan_accumulate(nec, nes, newChan, value); } } @@ -868,9 +943,47 @@ static void nlastrip_evaluate (PointerRNA *ptr, ListBase *channels, NlaEvalStrip } /* write the accumulated settings to */ -static void nladata_flush_channels (PointerRNA *ptr, ListBase *channels) +static void nladata_flush_channels (ListBase *channels) { + NlaEvalChannel *nec; + /* sanity checks */ + if (channels == NULL) + return; + + /* for each channel with accumulated values, write its value on the property it affects */ + for (nec= channels->first; nec; nec= nec->next) { + PointerRNA *ptr= &nec->ptr; + PropertyRNA *prop= nec->prop; + int array_index= nec->index; + float value= nec->value; + + /* write values - see animsys_write_rna_setting() to sync the code */ + switch (RNA_property_type(prop)) + { + case PROP_BOOLEAN: + if (RNA_property_array_length(prop)) + RNA_property_boolean_set_index(ptr, prop, array_index, (int)value); + else + RNA_property_boolean_set(ptr, prop, (int)value); + break; + case PROP_INT: + if (RNA_property_array_length(prop)) + RNA_property_int_set_index(ptr, prop, array_index, (int)value); + else + RNA_property_int_set(ptr, prop, (int)value); + break; + case PROP_FLOAT: + if (RNA_property_array_length(prop)) + RNA_property_float_set_index(ptr, prop, array_index, value); + else + RNA_property_float_set(ptr, prop, value); + break; + case PROP_ENUM: + RNA_property_enum_set(ptr, prop, (int)value); + break; + } + } } /* ---------------------- */ @@ -902,7 +1015,7 @@ static void animsys_evaluate_nla (PointerRNA *ptr, AnimData *adt, float ctime) nlastrip_evaluate(ptr, &echannels, nes); /* 3. flush effects of accumulating channels in NLA to the actual data they affect */ - nladata_flush_channels(ptr, &echannels); + nladata_flush_channels(&echannels); /* 4. free temporary evaluation data */ BLI_freelistN(&estrips); From 9b1ce6e55608e868a1fa1bc62710e053919c39de Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 22 May 2009 01:16:26 +0000 Subject: [PATCH 005/114] NLA SoC: Part 1 of NLA-Data Management API In this commit: * Added code for freeing NLA data now stored in AnimData * Started writing some utilities for adding NLA data, especially the 'push-down' concept for Actions * Cleanups of existing code - removal of obsolete NLA code from various places Next commits/parts: * File IO code for new-style NLA data * Version patching for old data to new data --- source/blender/blenkernel/BKE_nla.h | 33 +- source/blender/blenkernel/intern/anim_sys.c | 7 + source/blender/blenkernel/intern/nla.c | 389 ++++++++++++------- source/blender/blenkernel/intern/object.c | 8 +- source/blender/editors/space_nla/space_nla.c | 1 + source/blender/makesdna/DNA_anim_types.h | 4 +- source/blender/makesdna/DNA_space_types.h | 2 +- 7 files changed, 292 insertions(+), 152 deletions(-) diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index 230096d7ea7..0f23a5cb44d 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -17,12 +17,12 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung * All rights reserved. * * The Original Code is: all of this file. * - * Contributor(s): none yet. + * Contributor(s): Joshua Leung (full recode) * * ***** END GPL LICENSE BLOCK ***** */ @@ -30,15 +30,26 @@ #ifndef BKE_NLA_H #define BKE_NLA_H -struct bActionStrip; -struct ListBase; -struct Object; +struct AnimData; +struct NlaStrip; +struct NlaTrack; + +/* ----------------------------- */ +/* Data Management */ + +void free_nlastrip(ListBase *strips, struct NlaStrip *strip); +void free_nlatrack(ListBase *tracks, struct NlaTrack *nlt); +void free_nladata(ListBase *tracks); + +struct NlaTrack *add_nlatrack(struct AnimData *adt); + +/* ----------------------------- */ +/* API */ + +struct NlaTrack *BKE_nlatrack_find_active(ListBase *tracks); +void BKE_nlatrack_set_active(ListBase *tracks, struct NlaTrack *nlt_a); + +void BKE_nla_action_pushdown(struct AnimData *adt); -void free_actionstrip (struct bActionStrip* strip); -void free_nlastrips (struct ListBase *nlalist); -void copy_nlastrips (struct ListBase *dst, struct ListBase *src); -void copy_actionstrip (struct bActionStrip **dst, struct bActionStrip **src); -void find_stridechannel(struct Object *ob, struct bActionStrip *strip); -struct bActionStrip *convert_action_to_strip (struct Object *ob); #endif diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 702da23ef47..b47d734ef4f 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -17,6 +17,7 @@ #include "BKE_animsys.h" #include "BKE_action.h" #include "BKE_fcurve.h" +#include "BKE_nla.h" #include "BKE_global.h" #include "BKE_main.h" #include "BKE_utildefines.h" @@ -118,6 +119,9 @@ void BKE_free_animdata (ID *id) if (adt->action) adt->action->id.us--; + /* free nla data */ + free_nladata(&adt->nla_tracks); + /* free drivers - stored as a list of F-Curves */ free_fcurves(&adt->drivers); @@ -982,6 +986,9 @@ static void nladata_flush_channels (ListBase *channels) case PROP_ENUM: RNA_property_enum_set(ptr, prop, (int)value); break; + default: + // can't do anything with other types of property.... + break; } } } diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index dc2bf26759f..ac767fe86cc 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -17,171 +17,296 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung * All rights reserved. * * The Original Code is: all of this file. * - * Contributor(s): none yet. + * Contributor(s): Joshua Leung (full recode) * * ***** END GPL LICENSE BLOCK ***** */ #include +#include +#include +#include +#include #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" -#include "DNA_space_types.h" -#include "DNA_nla_types.h" +#include "DNA_anim_types.h" #include "DNA_action_types.h" -#include "DNA_ID.h" -#include "DNA_ipo_types.h" -#include "DNA_object_types.h" -#include "BKE_nla.h" +#include "BKE_animsys.h" #include "BKE_action.h" +#include "BKE_fcurve.h" +#include "BKE_nla.h" #include "BKE_blender.h" #include "BKE_library.h" -#include "BKE_object.h" /* for convert_action_to_strip(ob) */ +#include "BKE_object.h" +#include "BKE_utildefines.h" #ifdef HAVE_CONFIG_H #include #endif -/* NOTE: in group.c the strips get copied for group-nla override, this assumes - that strips are one single block, without additional data to be copied */ -void copy_actionstrip (bActionStrip **dst, bActionStrip **src){ - bActionStrip *dstrip; - bActionStrip *sstrip = *src; +/* *************************************************** */ +/* Data Management */ - if (!*src){ - *dst=NULL; +/* Freeing ------------------------------------------- */ + +/* Remove the given NLA strip from the NLA track it occupies, free the strip's data, + * and the strip itself. + */ +// TODO: with things like transitions, should these get freed too? Maybe better as a UI tool +void free_nlastrip (ListBase *strips, NlaStrip *strip) +{ + FModifier *fcm, *fmn; + + /* sanity checks */ + if (strip == NULL) return; - } - - *dst = MEM_dupallocN(sstrip); - - dstrip = *dst; - if (dstrip->act) - dstrip->act->id.us++; - - if (dstrip->ipo) - dstrip->ipo->id.us++; - - if (dstrip->modifiers.first) { - BLI_duplicatelist (&dstrip->modifiers, &sstrip->modifiers); - } - -} - -void copy_nlastrips (ListBase *dst, ListBase *src) -{ - bActionStrip *strip; - - dst->first=dst->last=NULL; - - BLI_duplicatelist (dst, src); - - /* Update specific data */ - if (!dst->first) - return; - - for (strip = dst->first; strip; strip=strip->next){ - if (strip->act) - strip->act->id.us++; - if (strip->ipo) - strip->ipo->id.us++; - if (strip->modifiers.first) { - ListBase listb; - BLI_duplicatelist (&listb, &strip->modifiers); - strip->modifiers= listb; - } - } -} - -/* from editnla, for convert_action_to_strip -- no UI code so should be ok here.. */ -void find_stridechannel(Object *ob, bActionStrip *strip) -{ - if(ob && ob->pose) { - bPoseChannel *pchan; - for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) - if(pchan->flag & POSE_STRIDE) - break; - if(pchan) - BLI_strncpy(strip->stridechannel, pchan->name, 32); - else - strip->stridechannel[0]= 0; - } -} - -//called by convert_nla / bpy api with an object with the action to be converted to a new strip -bActionStrip *convert_action_to_strip (Object *ob) -{ - bActionStrip *nstrip; - - /* Make new actionstrip */ - nstrip = MEM_callocN(sizeof(bActionStrip), "bActionStrip"); - - /* Link the action to the nstrip */ - nstrip->act = ob->action; - id_us_plus(&nstrip->act->id); - calc_action_range(nstrip->act, &nstrip->actstart, &nstrip->actend, 1); - nstrip->start = nstrip->actstart; - nstrip->end = nstrip->actend; - nstrip->flag = ACTSTRIP_SELECT|ACTSTRIP_LOCK_ACTION; - - find_stridechannel(ob, nstrip); - //set_active_strip(ob, nstrip); /* is in editnla as does UI calls */ - - nstrip->repeat = 1.0; - - if(ob->nlastrips.first == NULL) - ob->nlaflag |= OB_NLA_OVERRIDE; - - BLI_addtail(&ob->nlastrips, nstrip); - return nstrip; /* is created, malloced etc. here so is safe to just return the pointer? - this is needed for setting this active in UI, and probably useful for API too */ - -} - - -/* not strip itself! */ -void free_actionstrip(bActionStrip* strip) -{ - if (!strip) - return; - - if (strip->act){ + + /* remove reference to action */ + if (strip->act) strip->act->id.us--; - strip->act = NULL; - } - if (strip->ipo){ - strip->ipo->id.us--; - strip->ipo = NULL; - } - if (strip->modifiers.first) { - BLI_freelistN(&strip->modifiers); + + /* free remapping info */ + //if (strip->remap) + // BKE_animremap_free(); + + /* free own F-Curves */ + free_fcurves(&strip->fcurves); + + /* free F-Modifiers */ + for (fcm= strip->modifiers.first; fcm; fcm= fmn) { + fmn= fcm->next; + + BLI_remlink(&strip->modifiers, fcm); + fcurve_remove_modifier(NULL, fcm); } + /* free the strip itself */ + if (strips) + BLI_freelinkN(strips, strip); + else + MEM_freeN(strip); } -void free_nlastrips (ListBase *nlalist) +/* Remove the given NLA track from the set of NLA tracks, free the track's data, + * and the track itself. + */ +void free_nlatrack (ListBase *tracks, NlaTrack *nlt) { - bActionStrip *strip; - - if (!nlalist->first) + NlaStrip *strip, *stripn; + + /* sanity checks */ + if (nlt == NULL) return; - - /* Do any specific freeing */ - for (strip=nlalist->first; strip; strip=strip->next) - { - free_actionstrip (strip); - }; - - /* Free the whole list */ - BLI_freelistN(nlalist); + + /* free strips */ + for (strip= nlt->strips.first; strip; strip= stripn) { + stripn= strip->next; + free_nlastrip(&nlt->strips, strip); + } + + /* free NLA track itself now */ + if (tracks) + BLI_freelinkN(tracks, nlt); + else + MEM_freeN(nlt); } + +/* Free the elements of type NLA Tracks provided in the given list, but do not free + * the list itself since that is not free-standing + */ +void free_nladata (ListBase *tracks) +{ + NlaTrack *nlt, *nltn; + + /* sanity checks */ + if ELEM(NULL, tracks, tracks->first) + return; + + /* free tracks one by one */ + for (nlt= tracks->first; nlt; nlt= nltn) { + nltn= nlt->next; + free_nlatrack(tracks, nlt); + } + + /* clear the list's pointers to be safe */ + tracks->first= tracks->last= NULL; +} + +/* Copying ------------------------------------------- */ + +// TODO... + +/* Adding ------------------------------------------- */ + +/* Add a NLA Strip referencing the given Action, to the given NLA Track */ +// TODO: any extra parameters to control how this is done? +NlaStrip *add_nlastrip (NlaTrack *nlt, bAction *act) +{ + NlaStrip *strip; + + /* sanity checks */ + if ELEM(NULL, nlt, act) + return NULL; + + /* allocate new strip */ + strip= MEM_callocN(sizeof(NlaStrip), "NlaStrip"); + BLI_addtail(&nlt->strips, strip); + + /* generic settings + * - selected flag to highlight this to the user + * - auto-blends to ensure that blend in/out values are automatically + * determined by overlaps of strips + * - (XXX) synchronisation of strip-length in accordance with changes to action-length + * is not done though, since this should only really happens in editmode for strips now + * though this decision is still subject to further review... + */ + strip->flag = NLASTRIP_FLAG_SELECT|NLASTRIP_FLAG_AUTO_BLENDS; + + /* assign the action reference */ + strip->act= act; + id_us_plus(&act->id); + + /* determine initial range + * - strip length cannot be 0... ever... + */ + calc_action_range(strip->act, &strip->actstart, &strip->actend, 1); + + strip->start = strip->actstart; + strip->end = (IS_EQ(strip->actstart, strip->actend)) ? (strip->actstart + 1.0f): (strip->actend); + + /* strip should be referenced as-is */ + strip->scale= 1.0f; + strip->repeat = 1.0f; + + /* return the new strip */ + return strip; +} + +/* Add a NLA Track to the given AnimData */ +NlaTrack *add_nlatrack (AnimData *adt) +{ + NlaTrack *nlt; + + /* sanity checks */ + if (adt == NULL) + return NULL; + + /* allocate new track */ + nlt= MEM_callocN(sizeof(NlaTrack), "NlaTrack"); + + /* set settings requiring the track to not be part of the stack yet */ + nlt->flag = NLATRACK_SELECTED; + nlt->index= BLI_countlist(&adt->nla_tracks); + + /* add track to stack, and make it the active one */ + BLI_addtail(&adt->nla_tracks, nlt); + BKE_nlatrack_set_active(&adt->nla_tracks, nlt); + + /* must have unique name, but we need to seed this */ + sprintf(nlt->name, "NlaTrack"); + BLI_uniquename(&adt->nla_tracks, nlt, "NlaTrack", '.', offsetof(NlaTrack, name), 64); + + /* return the new track */ + return nlt; +} + +/* *************************************************** */ +/* Basic Utilities */ + +/* States ------------------------------------------- */ + +/* Find the active NLA-track for the given stack */ +NlaTrack *BKE_nlatrack_find_active (ListBase *tracks) +{ + NlaTrack *nlt; + + /* sanity check */ + if ELEM(NULL, tracks, tracks->first) + return NULL; + + /* try to find the first active track */ + for (nlt= tracks->first; nlt; nlt= nlt->next) { + if (nlt->flag & NLATRACK_ACTIVE) + return nlt; + } + + /* none found */ + return NULL; +} + +/* Make the given NLA-track the active one for the given stack. If no track is provided, + * this function can be used to simply deactivate all the NLA tracks in the given stack too. + */ +void BKE_nlatrack_set_active (ListBase *tracks, NlaTrack *nlt_a) +{ + NlaTrack *nlt; + + /* sanity check */ + if ELEM(NULL, tracks, tracks->first) + return; + + /* deactive all the rest */ + for (nlt= tracks->first; nlt; nlt= nlt->next) + nlt->flag &= ~NLATRACK_ACTIVE; + + /* set the given one as the active one */ + if (nlt_a) + nlt_a->flag |= NLATRACK_ACTIVE; +} + +/* Tools ------------------------------------------- */ + +/* For the given AnimData block, add the active action to the NLA + * stack (i.e. 'push-down' action). The UI should only allow this + * for normal editing only (i.e. not in editmode for some strip's action), + * so no checks for this are performed. + */ +// TODO: maybe we should have checks for this too... +void BKE_nla_action_pushdown (AnimData *adt) +{ + NlaTrack *nlt; + NlaStrip *strip; + + /* sanity checks */ + // TODO: need to report the error for this + if ELEM(NULL, adt, adt->action) + return; + + /* if the action is empty, we also shouldn't try to add to stack, + * as that will cause us grief down the track + */ + // TODO: code a method for this, and report errors after... + + /* add a new NLA track to house this action + * - we could investigate trying to fit the action into an appropriately + * sized gap in the existing tracks, however, this may result in unexpected + * changes in blending behaviour... + */ + nlt= add_nlatrack(adt); + if (nlt == NULL) + return; + + /* add a new NLA strip to the track, which references the active action */ + strip= add_nlastrip(nlt, adt->action); + + /* clear reference to action now that we've pushed it onto the stack */ + if (strip) { + adt->action->id.us--; + adt->action= NULL; + } + + // TODO: set any other flags necessary here... +} + +/* *************************************************** */ diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index b913651d856..b0902784687 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -1193,18 +1193,12 @@ Object *copy_object(Object *ob) armature_rebuild_pose(obn, obn->data); } copy_defgroups(&obn->defbase, &ob->defbase); -#if 0 // XXX old animation system - copy_nlastrips(&obn->nlastrips, &ob->nlastrips); -#endif // XXX old animation system copy_constraints(&obn->constraints, &ob->constraints); /* increase user numbers */ id_us_plus((ID *)obn->data); -#if 0 // XXX old animation system - id_us_plus((ID *)obn->ipo); - id_us_plus((ID *)obn->action); -#endif // XXX old animation system id_us_plus((ID *)obn->dup_group); + // FIXME: add this for animdata too... for(a=0; atotcol; a++) id_us_plus((ID *)obn->mat[a]); diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c index 6e1a97dea34..188315c73fb 100644 --- a/source/blender/editors/space_nla/space_nla.c +++ b/source/blender/editors/space_nla/space_nla.c @@ -29,6 +29,7 @@ #include #include +#include "DNA_anim_types.h" #include "DNA_nla_types.h" #include "DNA_object_types.h" #include "DNA_space_types.h" diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h index c0cdc1ab589..b20ec7ba37f 100644 --- a/source/blender/makesdna/DNA_anim_types.h +++ b/source/blender/makesdna/DNA_anim_types.h @@ -395,7 +395,7 @@ typedef struct AnimMapper { typedef struct NlaStrip { struct NlaStrip *next, *prev; - bAction *act; /* Action that is referenced by this strip */ + bAction *act; /* Action that is referenced by this strip (strip is 'user' of the action) */ AnimMapper *remap; /* Remapping info this strip (for tweaking correspondance of action with context) */ ListBase fcurves; /* F-Curves for controlling this strip's influence and timing */ // TODO: move out? @@ -458,6 +458,8 @@ enum { /* NLA strip is muted (i.e. doesn't contribute in any way) */ // TODO: this overlaps a lot with the functionality in track NLASTRIP_FLAG_MUTED = (1<<12), + /* NLA strip length is synced to the length of the referenced action */ + NLASTRIP_FLAG_SYNC_LENGTH = (1<<13), } eNlaStrip_Flag; /* NLA Strip Type */ diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 0e19a6845da..0a4fe1c5814 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -244,7 +244,7 @@ typedef struct SpaceNla { short blockhandler[8]; - short menunr, lock; + int filterflag; /* filtering flags (similar to the ones used for Keyframe Editors) */ short autosnap; /* this uses the same settings as autosnap for Action Editor */ short flag; From 3b7f63a0884c6ec9db5abb938708f4191ea35274 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 22 May 2009 11:19:35 +0000 Subject: [PATCH 006/114] NLA SoC: File IO for new NLA Datatypes --- source/blender/blenkernel/BKE_nla.h | 2 + source/blender/blenloader/intern/readfile.c | 149 +++++++++++++------ source/blender/blenloader/intern/writefile.c | 125 ++++++++++------ 3 files changed, 186 insertions(+), 90 deletions(-) diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index 0f23a5cb44d..3864d9da5f6 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -33,6 +33,7 @@ struct AnimData; struct NlaStrip; struct NlaTrack; +struct bAction; /* ----------------------------- */ /* Data Management */ @@ -41,6 +42,7 @@ void free_nlastrip(ListBase *strips, struct NlaStrip *strip); void free_nlatrack(ListBase *tracks, struct NlaTrack *nlt); void free_nladata(ListBase *tracks); +struct NlaStrip *add_nlastrip(struct NlaTrack *nlt, struct bAction *act); struct NlaTrack *add_nlatrack(struct AnimData *adt); /* ----------------------------- */ diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index fd9da2059e1..cfb8baa4c84 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -1657,10 +1657,26 @@ static void lib_link_constraint_channels(FileData *fd, ID *id, ListBase *chanbas /* Data Linking ----------------------------- */ +static void lib_link_fmodifiers(FileData *fd, ID *id, ListBase *list) +{ + FModifier *fcm; + + for (fcm= list->first; fcm; fcm= fcm->next) { + /* data for specific modifiers */ + switch (fcm->type) { + case FMODIFIER_TYPE_PYTHON: + { + FMod_Python *data= (FMod_Python *)fcm->data; + data->script = newlibadr(fd, id->lib, data->script); + } + break; + } + } +} + static void lib_link_fcurves(FileData *fd, ID *id, ListBase *list) { FCurve *fcu; - FModifier *fcm; /* relink ID-block references... */ for (fcu= list->first; fcu; fcu= fcu->next) { @@ -1674,16 +1690,45 @@ static void lib_link_fcurves(FileData *fd, ID *id, ListBase *list) } /* modifiers */ - for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next) { - /* data for specific modifiers */ - switch (fcm->type) { - case FMODIFIER_TYPE_PYTHON: - { - FMod_Python *data= (FMod_Python *)fcm->data; - data->script = newlibadr(fd, id->lib, data->script); - } - break; + lib_link_fmodifiers(fd, id, &fcu->modifiers); + } +} + + +/* NOTE: this assumes that link_list has already been called on the list */ +static void direct_link_fmodifiers(FileData *fd, ListBase *list) +{ + FModifier *fcm; + + for (fcm= list->first; fcm; fcm= fcm->next) { + /* relink general data */ + fcm->data = newdataadr(fd, fcm->data); + fcm->edata= NULL; + + /* do relinking of data for specific types */ + switch (fcm->type) { + case FMODIFIER_TYPE_GENERATOR: + { + FMod_Generator *data= (FMod_Generator *)fcm->data; + + data->coefficients= newdataadr(fd, data->coefficients); } + break; + case FMODIFIER_TYPE_ENVELOPE: + { + FMod_Envelope *data= (FMod_Envelope *)fcm->data; + + data->data= newdataadr(fd, data->data); + } + break; + case FMODIFIER_TYPE_PYTHON: + { + FMod_Python *data= (FMod_Python *)fcm->data; + + data->prop = newdataadr(fd, data->prop); + IDP_DirectLinkProperty(data->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + } + break; } } } @@ -1692,7 +1737,6 @@ static void lib_link_fcurves(FileData *fd, ID *id, ListBase *list) static void direct_link_fcurves(FileData *fd, ListBase *list) { FCurve *fcu; - FModifier *fcm; /* link F-Curve data to F-Curve again (non ID-libs) */ for (fcu= list->first; fcu; fcu= fcu->next) { @@ -1720,37 +1764,7 @@ static void direct_link_fcurves(FileData *fd, ListBase *list) /* modifiers */ link_list(fd, &fcu->modifiers); - for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next) { - /* relink general data */ - fcm->data = newdataadr(fd, fcm->data); - fcm->edata= NULL; - - /* do relinking of data for specific types */ - switch (fcm->type) { - case FMODIFIER_TYPE_GENERATOR: - { - FMod_Generator *data= (FMod_Generator *)fcm->data; - - data->coefficients= newdataadr(fd, data->coefficients); - } - break; - case FMODIFIER_TYPE_ENVELOPE: - { - FMod_Envelope *data= (FMod_Envelope *)fcm->data; - - data->data= newdataadr(fd, data->data); - } - break; - case FMODIFIER_TYPE_PYTHON: - { - FMod_Python *data= (FMod_Python *)fcm->data; - - data->prop = newdataadr(fd, data->prop); - IDP_DirectLinkProperty(data->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); - } - break; - } - } + direct_link_fmodifiers(fd, &fcu->modifiers); } } @@ -1802,6 +1816,44 @@ static void direct_link_action(FileData *fd, bAction *act) } } + +static void lib_link_nladata (FileData *fd, ID *id, ListBase *list) +{ + NlaTrack *nlt; + NlaStrip *strip; + + /* we only acare about the NLA strips inside the tracks */ + for (nlt= list->first; nlt; nlt= nlt->next) { + for (strip= nlt->strips.first; strip; strip= strip->next) { + /* reassign the counted-reference to action */ + strip->act = newlibadr_us(fd, id->lib, strip->act); + } + } +} + +/* NOTE: this assumes that link_list has already been called on the list */ +static void direct_link_nladata(FileData *fd, ListBase *list) +{ + NlaTrack *nlt; + NlaStrip *strip; + + for (nlt= list->first; nlt; nlt= nlt->next) { + /* relink list of strips */ + link_list(fd, &nlt->strips); + + /* relink strip data */ + for (strip= nlt->strips.first; strip; strip= strip->next) { + /* strip's F-Curves */ + link_list(fd, &strip->fcurves); + direct_link_fcurves(fd, &strip->fcurves); + + /* strip's F-Modifiers */ + link_list(fd, &strip->modifiers); + direct_link_fcurves(fd, &strip->modifiers); + } + } +} + /* ------- */ static void lib_link_keyingsets(FileData *fd, ID *id, ListBase *list) @@ -1851,7 +1903,7 @@ static void lib_link_animdata(FileData *fd, ID *id, AnimData *adt) /* overrides don't have lib-link for now, so no need to do anything */ /* link NLA-data */ - // TODO... + lib_link_nladata(fd, id, &adt->nla_tracks); } static void direct_link_animdata(FileData *fd, AnimData *adt) @@ -1868,7 +1920,8 @@ static void direct_link_animdata(FileData *fd, AnimData *adt) // TODO... /* link NLA-data */ - // TODO... + link_list(fd, &adt->nla_tracks); + direct_link_nladata(fd, &adt->nla_tracks); } /* ************ READ NODE TREE *************** */ @@ -9302,6 +9355,8 @@ static void expand_keyingsets(FileData *fd, Main *mainvar, ListBase *list) static void expand_animdata(FileData *fd, Main *mainvar, AnimData *adt) { FCurve *fcd; + NlaTrack *nlt; + NlaStrip *strip; /* own action */ expand_doit(fd, mainvar, adt->action); @@ -9314,6 +9369,12 @@ static void expand_animdata(FileData *fd, Main *mainvar, AnimData *adt) for (dtar= driver->targets.first; dtar; dtar= dtar->next) expand_doit(fd, mainvar, dtar->id); } + + /* nla-data - referenced actions */ + for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) { + for (strip= nlt->strips.first; strip; strip= strip->next) + expand_doit(fd, mainvar, strip->act); + } } static void expand_particlesettings(FileData *fd, Main *mainvar, ParticleSettings *part) diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index b690c708dc3..0375feffb31 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -760,10 +760,59 @@ static void write_actuators(WriteData *wd, ListBase *lb) } } +static void write_fmodifiers(WriteData *wd, ListBase *fmodifiers) +{ + FModifier *fcm; + + /* Modifiers */ + for (fcm= fmodifiers->first; fcm; fcm= fcm->next) { + FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); + + /* Write the specific data */ + if (fmi && fcm->data) { + /* firstly, just write the plain fmi->data struct */ + writestruct(wd, DATA, fmi->structName, 1, fcm->data); + + /* do any modifier specific stuff */ + switch (fcm->type) { + case FMODIFIER_TYPE_GENERATOR: + { + FMod_Generator *data= (FMod_Generator *)fcm->data; + + /* write coefficients array */ + if (data->coefficients) + writedata(wd, DATA, sizeof(float)*(data->arraysize), data->coefficients); + } + break; + case FMODIFIER_TYPE_ENVELOPE: + { + FMod_Envelope *data= (FMod_Envelope *)fcm->data; + + /* write envelope data */ + if (data->data) + writedata(wd, DATA, sizeof(FCM_EnvelopeData)*(data->totvert), data->data); + } + break; + case FMODIFIER_TYPE_PYTHON: + { + FMod_Python *data = (FMod_Python *)fcm->data; + + /* Write ID Properties -- and copy this comment EXACTLY for easy finding + of library blocks that implement this.*/ + IDP_WriteProperty(data->prop, wd); + } + break; + } + } + + /* Write the modifier */ + writestruct(wd, DATA, "FModifier", 1, fcm); + } +} + static void write_fcurves(WriteData *wd, ListBase *fcurves) { FCurve *fcu; - FModifier *fcm; for (fcu=fcurves->first; fcu; fcu=fcu->next) { /* F-Curve */ @@ -794,50 +843,8 @@ static void write_fcurves(WriteData *wd, ListBase *fcurves) } } - /* Modifiers */ - for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next) { - FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); - - /* Write the specific data */ - if (fmi && fcm->data) { - /* firstly, just write the plain fmi->data struct */ - writestruct(wd, DATA, fmi->structName, 1, fcm->data); - - /* do any modifier specific stuff */ - switch (fcm->type) { - case FMODIFIER_TYPE_GENERATOR: - { - FMod_Generator *data= (FMod_Generator *)fcm->data; - - /* write coefficients array */ - if (data->coefficients) - writedata(wd, DATA, sizeof(float)*(data->arraysize), data->coefficients); - } - break; - case FMODIFIER_TYPE_ENVELOPE: - { - FMod_Envelope *data= (FMod_Envelope *)fcm->data; - - /* write envelope data */ - if (data->data) - writedata(wd, DATA, sizeof(FCM_EnvelopeData)*(data->totvert), data->data); - } - break; - case FMODIFIER_TYPE_PYTHON: - { - FMod_Python *data = (FMod_Python *)fcm->data; - - /* Write ID Properties -- and copy this comment EXACTLY for easy finding - of library blocks that implement this.*/ - IDP_WriteProperty(data->prop, wd); - } - break; - } - } - - /* Write the modifier */ - writestruct(wd, DATA, "FModifier", 1, fcm); - } + /* write F-Modifiers */ + write_fmodifiers(wd, &fcu->modifiers); } } @@ -888,6 +895,29 @@ static void write_keyingsets(WriteData *wd, ListBase *list) } } +static void write_nladata(WriteData *wd, ListBase *nlabase) +{ + NlaTrack *nlt; + NlaStrip *strip; + + /* write all the tracks */ + for (nlt= nlabase->first; nlt; nlt= nlt->next) { + /* write the track first */ + writestruct(wd, DATA, "NlaTrack", 1, nlt); + + for (strip= nlt->strips.first; strip; strip= strip->next) { + /* write the strip first */ + writestruct(wd, DATA, "NlaStrip", 1, strip); + + /* write the strip's F-Curves and modifiers */ + write_fcurves(wd, &strip->fcurves); + write_fmodifiers(wd, &strip->modifiers); + + // TODO write the remaps + } + } +} + static void write_animdata(WriteData *wd, AnimData *adt) { AnimOverride *aor; @@ -899,14 +929,17 @@ static void write_animdata(WriteData *wd, AnimData *adt) write_fcurves(wd, &adt->drivers); /* write overrides */ + // FIXME: are these needed? for (aor= adt->overrides.first; aor; aor= aor->next) { /* overrides consist of base data + rna_path */ writestruct(wd, DATA, "AnimOverride", 1, aor); writedata(wd, DATA, strlen(aor->rna_path)+1, aor->rna_path); } + // TODO write the remaps (if they are needed) + /* write NLA data */ - // XXX todo... + write_nladata(wd, &adt->nla_tracks); } static void write_constraints(WriteData *wd, ListBase *conlist) From d141aff097d17c106071f2ad966fdd97a1fb5ba4 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sat, 23 May 2009 09:36:18 +0000 Subject: [PATCH 007/114] NLA SoC: Adding more backend code/utilities * Data copying * Strip sorting --- source/blender/blenkernel/BKE_action.h | 3 + source/blender/blenkernel/BKE_nla.h | 9 +- source/blender/blenkernel/intern/action.c | 17 ++- source/blender/blenkernel/intern/anim_sys.c | 2 +- source/blender/blenkernel/intern/nla.c | 148 +++++++++++++++++++- 5 files changed, 173 insertions(+), 6 deletions(-) diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index 67eb2ed58bf..cc10a4071a6 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -68,6 +68,9 @@ void make_local_action(struct bAction *act); /* Some kind of bounding box operation on the action */ void calc_action_range(const struct bAction *act, float *start, float *end, int incl_hidden); +/* Does action have any motion data at all? */ +short action_has_motion(const struct bAction *act); + /* Action Groups API ----------------- */ /* Make the given Action Group the active one */ diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index 3864d9da5f6..49796250633 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -42,6 +42,10 @@ void free_nlastrip(ListBase *strips, struct NlaStrip *strip); void free_nlatrack(ListBase *tracks, struct NlaTrack *nlt); void free_nladata(ListBase *tracks); +struct NlaStrip *copy_nlastrip(struct NlaStrip *strip); +struct NlaTrack *copy_nlatrack(struct NlaTrack *nlt); +void copy_nladata(ListBase *dst, ListBase *src); + struct NlaStrip *add_nlastrip(struct NlaTrack *nlt, struct bAction *act); struct NlaTrack *add_nlatrack(struct AnimData *adt); @@ -49,7 +53,10 @@ struct NlaTrack *add_nlatrack(struct AnimData *adt); /* API */ struct NlaTrack *BKE_nlatrack_find_active(ListBase *tracks); -void BKE_nlatrack_set_active(ListBase *tracks, struct NlaTrack *nlt_a); +void BKE_nlatrack_set_active(ListBase *tracks, struct NlaTrack *nlt); + +short BKE_nlatrack_has_space(struct NlaTrack *nlt, float start, float end); +void BKE_nlatrack_sort_strips(struct NlaTrack *nlt); void BKE_nla_action_pushdown(struct AnimData *adt); diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index f2e3583c87b..bb458cc7e25 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -740,7 +740,22 @@ float get_action_frame_inv(Object *ob, float cframe) } - +/* Check if the given action has any keyframes */ +short action_has_motion(const bAction *act) +{ + FCurve *fcu; + + /* return on the first F-Curve that has some keyframes/samples defined */ + if (act) { + for (fcu= act->curves.first; fcu; fcu= fcu->next) { + if (fcu->totvert) + return 1; + } + } + + /* nothing found */ + return 0; +} /* Calculate the extents of given action */ void calc_action_range(const bAction *act, float *start, float *end, int incl_hidden) diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index b47d734ef4f..f21fed416cc 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -153,7 +153,7 @@ AnimData *BKE_copy_animdata (AnimData *adt) dadt->action= copy_action(adt->action); /* duplicate NLA data */ - // XXX todo... + copy_nladata(&dadt->nla_tracks, &adt->nla_tracks); /* duplicate drivers (F-Curves) */ copy_fcurves(&dadt->drivers, &adt->drivers); diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index ac767fe86cc..d062a2ab14b 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -145,7 +145,73 @@ void free_nladata (ListBase *tracks) /* Copying ------------------------------------------- */ -// TODO... +/* Copy NLA strip */ +NlaStrip *copy_nlastrip (NlaStrip *strip) +{ + NlaStrip *strip_d; + + /* sanity check */ + if (strip == NULL) + return NULL; + + /* make a copy */ + strip_d= MEM_dupallocN(strip); + strip_d->next= strip_d->prev= NULL; + + /* increase user-count of action */ + if (strip_d->act) + strip_d->act->id.us++; + + /* copy F-Curves and modifiers */ + copy_fcurves(&strip_d->fcurves, &strip->fcurves); + fcurve_copy_modifiers(&strip_d->modifiers, &strip->modifiers); + + /* return the strip */ + return strip_d; +} + +/* Copy NLA Track */ +NlaTrack *copy_nlatrack (NlaTrack *nlt) +{ + NlaStrip *strip, *strip_d; + NlaTrack *nlt_d; + + /* sanity check */ + if (nlt == NULL) + return NULL; + + /* make a copy */ + nlt_d= MEM_dupallocN(nlt); + nlt_d->next= nlt_d->prev= NULL; + + /* make a copy of all the strips, one at a time */ + nlt_d->strips.first= nlt_d->strips.last= NULL; + + for (strip= nlt->strips.first; strip; strip= strip->next) { + strip_d= copy_nlastrip(strip); + BLI_addtail(&nlt_d->strips, strip_d); + } + + /* return the copy */ + return nlt_d; +} + +/* Copy all NLA data */ +void copy_nladata (ListBase *dst, ListBase *src) +{ + NlaTrack *nlt, *nlt_d; + + /* sanity checks */ + if ELEM(NULL, dst, src) + return; + + /* copy each NLA-track, one at a time */ + for (nlt= src->first; nlt; nlt= nlt->next) { + /* make a copy, and add the copy to the destination list */ + nlt_d= copy_nlatrack(nlt); + BLI_addtail(dst, nlt_d); + } +} /* Adding ------------------------------------------- */ @@ -224,7 +290,7 @@ NlaTrack *add_nlatrack (AnimData *adt) /* *************************************************** */ /* Basic Utilities */ -/* States ------------------------------------------- */ +/* NLA-Tracks ---------------------------------------- */ /* Find the active NLA-track for the given stack */ NlaTrack *BKE_nlatrack_find_active (ListBase *tracks) @@ -265,6 +331,80 @@ void BKE_nlatrack_set_active (ListBase *tracks, NlaTrack *nlt_a) nlt_a->flag |= NLATRACK_ACTIVE; } +/* Check if there is any space in the last track to add the given strip */ +short BKE_nlatrack_has_space (NlaTrack *nlt, float start, float end) +{ + NlaStrip *strip; + + /* sanity checks */ + if ((nlt == NULL) || IS_EQ(start, end)) + return 0; + if (start > end) { + puts("BKE_nlatrack_has_space error... start and end arguments swapped"); + SWAP(float, start, end); + } + + /* loop over NLA strips checking for any overlaps with this area... */ + for (strip= nlt->strips.first; strip; strip= strip->next) { + /* if start frame of strip is past the target end-frame, that means that + * we've gone past the window we need to check for, so things are fine + */ + if (strip->start > end) + return 1; + + /* if the end of the strip is greater than either of the boundaries, the range + * must fall within the extents of the strip + */ + if ((strip->end > start) || (strip->end > end)) + return 0; + } + + /* if we are still here, we haven't encountered any overlapping strips */ + return 1; +} + +/* Rearrange the strips in the track so that they are always in order + * (usually only needed after a strip has been moved) + */ +void BKE_nlatrack_sort_strips (NlaTrack *nlt) +{ + ListBase tmp = {NULL, NULL}; + NlaStrip *strip, *sstrip; + + /* sanity checks */ + if ELEM(NULL, nlt, nlt->strips.first) + return; + + /* we simply perform insertion sort on this list, since it is assumed that per track, + * there are only likely to be at most 5-10 strips + */ + for (strip= nlt->strips.first; strip; strip= strip->next) { + short not_added = 1; + + /* remove this strip from the list, and add it to the new list, searching from the end of + * the list, assuming that the lists are in order + */ + BLI_remlink(&nlt->strips, strip); + + for (sstrip= tmp.last; not_added && sstrip; sstrip= sstrip->prev) { + /* check if add after */ + if (sstrip->end < strip->start) { + BLI_insertlinkafter(&tmp, sstrip, strip); + not_added= 0; + break; + } + } + + /* add before first? */ + if (not_added) + BLI_addhead(&tmp, strip); + } + + /* reassign the start and end points of the strips */ + nlt->strips.first= tmp.first; + nlt->strips.last= tmp.last; +} + /* Tools ------------------------------------------- */ /* For the given AnimData block, add the active action to the NLA @@ -286,7 +426,9 @@ void BKE_nla_action_pushdown (AnimData *adt) /* if the action is empty, we also shouldn't try to add to stack, * as that will cause us grief down the track */ - // TODO: code a method for this, and report errors after... + // TODO: what about modifiers? + if (action_has_motion(adt->action) == 0) + return; /* add a new NLA track to house this action * - we could investigate trying to fit the action into an appropriately From 801eeb6423f4fcd3f2b2fac73cc5e65c96654c5b Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Mon, 25 May 2009 13:07:54 +0000 Subject: [PATCH 008/114] NLA SoC: Groundwork for NLA UI Adapted the channel-filtering code for the other animation editors for eventual use by the NLA Editor. --- source/blender/blenloader/intern/readfile.c | 5 + source/blender/blenloader/intern/writefile.c | 5 +- .../blender/editors/animation/anim_filter.c | 464 +++++++++++------- source/blender/editors/include/ED_anim_api.h | 14 +- source/blender/editors/space_nla/space_nla.c | 9 +- source/blender/makesdna/DNA_action_types.h | 1 + source/blender/makesdna/DNA_space_types.h | 3 +- 7 files changed, 317 insertions(+), 184 deletions(-) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index cfb8baa4c84..c919a6dd6a9 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -4679,6 +4679,11 @@ static void direct_link_screen(FileData *fd, bScreen *sc) sipo->ads= newdataadr(fd, sipo->ads); sipo->ghostCurves.first= sipo->ghostCurves.last= NULL; } + else if (sl->spacetype==SPACE_NLA) { + SpaceNla *snla= (SpaceNla*)sl; + + snla->ads= newdataadr(fd, snla->ads); + } else if (sl->spacetype==SPACE_OUTLINER) { SpaceOops *soops= (SpaceOops*) sl; diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 0375feffb31..bb1ee15eaea 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -1904,7 +1904,10 @@ static void write_screens(WriteData *wd, ListBase *scrbase) writestruct(wd, DATA, "SpaceSound", 1, sl); } else if(sl->spacetype==SPACE_NLA){ - writestruct(wd, DATA, "SpaceNla", 1, sl); + SpaceNla *snla= (SpaceNla *)sl; + + writestruct(wd, DATA, "SpaceNla", 1, snla); + if(snla->ads) writestruct(wd, DATA, "bDopeSheet", 1, snla->ads); } else if(sl->spacetype==SPACE_TIME){ writestruct(wd, DATA, "SpaceTime", 1, sl); diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index afad396607b..69e4fbfb08e 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -195,7 +195,7 @@ static short actedit_get_context (bAnimContext *ac, SpaceAction *saction) } } -/* ----------- Private Stuff - IPO Editor ------------- */ +/* ----------- Private Stuff - Graph Editor ------------- */ /* Get data being edited in Graph Editor (depending on current 'mode') */ static short graphedit_get_context (bAnimContext *ac, SpaceIpo *sipo) @@ -237,6 +237,26 @@ static short graphedit_get_context (bAnimContext *ac, SpaceIpo *sipo) } } +/* ----------- Private Stuff - NLA Editor ------------- */ + +/* Get data being edited in Graph Editor (depending on current 'mode') */ +static short nlaedit_get_context (bAnimContext *ac, SpaceNla *snla) +{ + /* init dopesheet data if non-existant (i.e. for old files) */ + if (snla->ads == NULL) + snla->ads= MEM_callocN(sizeof(bDopeSheet), "GraphEdit DopeSheet"); + + /* sync settings with current view status, then return appropriate data */ + /* update scene-pointer (no need to check for pinning yet, as not implemented) */ + snla->ads->source= (ID *)ac->scene; + snla->ads->filterflag |= ADS_FILTER_ONLYNLA; + + ac->datatype= ANIMCONT_NLA; + ac->data= snla->ads; + + return 1; +} + /* ----------- Public API --------------- */ /* Obtain current anim-data context, given that context info from Blender context has already been set @@ -264,6 +284,13 @@ short ANIM_animdata_context_getdata (bAnimContext *ac) ok= graphedit_get_context(ac, sipo); } break; + + case SPACE_NLA: + { + SpaceNla *snla= (SpaceNla *)sa->spacedata.first; + ok= nlaedit_get_context(ac, snla); + } + break; } } @@ -313,6 +340,39 @@ short ANIM_animdata_get_context (const bContext *C, bAnimContext *ac) /* quick macro to test if AnimData is usable for drivers */ #define ANIMDATA_HAS_DRIVERS(id) ((id)->adt && (id)->adt->drivers.first) +/* quick macro to test if AnimData is usable for NLA */ +#define ANIMDATA_HAS_NLA(id) ((id)->adt && (id)->adt->nla_tracks.first) + +/* quick macro to test for all three avove usability tests, performing the appropriate provided + * action for each when the AnimData context is appropriate. + * + * Priority order for this goes (most important, to least): NLA, Drivers, Keyframes + * + * - id: ID block which should have an AnimData pointer following it immediately, to use + * - nlaOk: line or block of code to execute for NLA case + * - driversOk: line or block of code to execute for Drivers case + * - keysOk: line or block of code for Keyframes case + */ +#define ANIMDATA_FILTER_CASES(id, nlaOk, driversOk, keysOk) \ + {\ + if (ads->filterflag & ADS_FILTER_ONLYNLA) {\ + if (ANIMDATA_HAS_NLA(id)) {\ + nlaOk\ + }\ + }\ + else if (ads->filterflag & ADS_FILTER_ONLYDRIVERS) {\ + if (ANIMDATA_HAS_DRIVERS(id)) {\ + driversOk\ + }\ + }\ + else {\ + if (ANIMDATA_HAS_KEYS(id)) {\ + keysOk\ + }\ + }\ + } + + /* quick macro to test if a anim-channel (F-Curve, Group, etc.) is selected in an acceptable way */ #define ANIMCHANNEL_SELOK(test_func) \ ( !(filter_mode & (ANIMFILTER_SEL|ANIMFILTER_UNSEL)) || \ @@ -494,6 +554,18 @@ bAnimListElem *make_new_animlistelem (void *data, short datatype, void *owner, s ale->datatype= ALE_GPFRAME; } break; + + case ANIMTYPE_NLATRACK: + { + NlaTrack *nlt= (NlaTrack *)data; + + ale->flag= nlt->flag; + + // XXX or should this be done some other way? + ale->key_data= &nlt->strips; + ale->datatype= ALE_NLASTRIP; + } + break; } } @@ -610,6 +682,12 @@ static int animdata_filter_action (ListBase *anim_data, bAction *act, int filter return items; } +static int animdata_filter_nla (ListBase *anim_data, NlaTrack *first, int filter_mode, void *owner, short ownertype, ID *owner_id) +{ + // FIXME + return 0; +} + static int animdata_filter_shapekey (ListBase *anim_data, Key *key, int filter_mode, void *owner, short ownertype, ID *owner_id) { bAnimListElem *ale; @@ -752,19 +830,18 @@ static int animdata_filter_dopesheet_mats (ListBase *anim_data, bDopeSheet *ads, /* firstly check that we actuallly have some materials, by gathering all materials in a temp list */ for (a=0; a < ob->totcol; a++) { Material *ma= give_current_material(ob, a); + short ok = 0; /* for now, if no material returned, skip (this shouldn't confuse the user I hope) */ if (ELEM(NULL, ma, ma->adt)) continue; - if ((ads->filterflag & ADS_FILTER_ONLYDRIVERS)==0) { - if (ANIMDATA_HAS_KEYS(ma) == 0) - continue; - } - else { - if (ANIMDATA_HAS_DRIVERS(ma) == 0) - continue; - } + /* check if ok */ + ANIMDATA_FILTER_CASES(ma, + ok=1;, + ok=1;, + ok=1;) + if (ok == 0) continue; /* make a temp list elem for this */ ld= MEM_callocN(sizeof(LinkData), "DopeSheet-MaterialCache"); @@ -801,16 +878,12 @@ static int animdata_filter_dopesheet_mats (ListBase *anim_data, bDopeSheet *ads, } } - /* add material's F-Curve or Driver channels? */ + /* add material's animation data */ if (FILTER_MAT_OBJD(ma) || (filter_mode & ANIMFILTER_CURVESONLY)) { - if ((ads->filterflag & ADS_FILTER_ONLYDRIVERS)==0) { - // XXX the 'owner' info here is still subject to improvement - items += animdata_filter_action(anim_data, ma->adt->action, filter_mode, ma, ANIMTYPE_DSMAT, (ID *)ma); - } - else { - // need to make the ownertype normal object here... (maybe type should be a separate one for clarity?) - items += animdata_filter_fcurves(anim_data, ma->adt->drivers.first, NULL, ma, ANIMTYPE_DSMAT, filter_mode, (ID *)ma); - } + ANIMDATA_FILTER_CASES(ma, + items += animdata_filter_nla(anim_data, ma->adt->nla_tracks.first, filter_mode, ma, ANIMTYPE_DSMAT, (ID *)ma);, + items += animdata_filter_fcurves(anim_data, ma->adt->drivers.first, NULL, ma, ANIMTYPE_DSMAT, filter_mode, (ID *)ma);, + items += animdata_filter_action(anim_data, ma->adt->action, filter_mode, ma, ANIMTYPE_DSMAT, (ID *)ma);) } } } @@ -871,15 +944,11 @@ static int animdata_filter_dopesheet_obdata (ListBase *anim_data, bDopeSheet *ad /* add object-data animation channels? */ if ((expanded) || (filter_mode & ANIMFILTER_CURVESONLY)) { - /* Action or Drivers? */ - if ((ads->filterflag & ADS_FILTER_ONLYDRIVERS) == 0) { - // XXX the 'owner' info here is still subject to improvement - items += animdata_filter_action(anim_data, iat->adt->action, filter_mode, iat, type, (ID *)iat); - } - else { - // need to make the ownertype normal object here... (maybe type should be a separate one for clarity?) - items += animdata_filter_fcurves(anim_data, adt->drivers.first, NULL, iat, type, filter_mode, (ID *)iat); - } + /* filtering for channels - nla, drivers, keyframes */ + ANIMDATA_FILTER_CASES(iat, + items+= animdata_filter_nla(anim_data, iat->adt->nla_tracks.first, filter_mode, iat, type, (ID *)iat);, + items+= animdata_filter_fcurves(anim_data, adt->drivers.first, NULL, iat, type, filter_mode, (ID *)iat);, + items += animdata_filter_action(anim_data, iat->adt->action, filter_mode, iat, type, (ID *)iat);) } /* return the number of items added to the list */ @@ -889,8 +958,10 @@ static int animdata_filter_dopesheet_obdata (ListBase *anim_data, bDopeSheet *ad static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode) { bAnimListElem *ale=NULL; + AnimData *adt = NULL; Object *ob= base->object; Key *key= ob_get_key(ob); + short obdata_ok = 0; int items = 0; /* add this object as a channel first */ @@ -909,73 +980,83 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B if ( (EXPANDED_OBJC(ob) == 0) && !(filter_mode & ANIMFILTER_CURVESONLY) ) return items; - /* Action or Drivers */ - if ((ads->filterflag & ADS_FILTER_ONLYDRIVERS) == 0) { - /* Action? */ - if (ANIMDATA_HAS_KEYS(ob) /*&& !(ads->filterflag & ADS_FILTER_NOACTS)*/) { - AnimData *adt= ob->adt; - - /* include action-expand widget? */ - if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) { - ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLACTD, base, ANIMTYPE_OBJECT, (ID *)ob); - if (ale) { - BLI_addtail(anim_data, ale); - items++; + /* Action, Drivers, or NLA */ + if (ob->adt) { + adt= ob->adt; + ANIMDATA_FILTER_CASES(ob, + { /* nla */ +#if 0 + /* include nla-expand widget? */ + if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) { + ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLNLA, base, ANIMTYPE_OBJECT, (ID *)ob); + if (ale) { + BLI_addtail(anim_data, ale); + items++; + } + } +#endif + + /* add NLA tracks */ + if (/*EXPANDED_NLTD(adt) ||*/ !(filter_mode & ANIMFILTER_CHANNELS)) + items += animdata_filter_nla(anim_data, adt->nla_tracks.first, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob); + }, + { /* drivers */ + /* include drivers-expand widget? */ + if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) { + ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLDRIVERS, base, ANIMTYPE_OBJECT, (ID *)ob); + if (ale) { + BLI_addtail(anim_data, ale); + items++; + } + } + + /* add F-Curve channels (drivers are F-Curves) */ + if (EXPANDED_DRVD(adt) || !(filter_mode & ANIMFILTER_CHANNELS)) { + // need to make the ownertype normal object here... (maybe type should be a separate one for clarity?) + items += animdata_filter_fcurves(anim_data, adt->drivers.first, NULL, ob, ANIMTYPE_OBJECT, filter_mode, (ID *)ob); + } + }, + { /* action (keyframes) */ + /* include action-expand widget? */ + if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) { + ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLACTD, base, ANIMTYPE_OBJECT, (ID *)ob); + if (ale) { + BLI_addtail(anim_data, ale); + items++; + } + } + + /* add F-Curve channels? */ + if (EXPANDED_ACTC(adt->action) || !(filter_mode & ANIMFILTER_CHANNELS)) { + // need to make the ownertype normal object here... (maybe type should be a separate one for clarity?) + items += animdata_filter_action(anim_data, adt->action, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob); } } - - /* add F-Curve channels? */ - if (EXPANDED_ACTC(adt->action) || !(filter_mode & ANIMFILTER_CHANNELS)) { - // need to make the ownertype normal object here... (maybe type should be a separate one for clarity?) - items += animdata_filter_action(anim_data, adt->action, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob); - } - } - } - else { - /* Drivers */ - if (ANIMDATA_HAS_DRIVERS(ob)) { - AnimData *adt= ob->adt; - - /* include drivers-expand widget? */ - if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) { - ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLDRIVERS, base, ANIMTYPE_OBJECT, (ID *)ob); - if (ale) { - BLI_addtail(anim_data, ale); - items++; - } - } - - /* add F-Curve channels (drivers are F-Curves) */ - if (EXPANDED_DRVD(adt) || !(filter_mode & ANIMFILTER_CHANNELS)) { - // need to make the ownertype normal object here... (maybe type should be a separate one for clarity?) - items += animdata_filter_fcurves(anim_data, adt->drivers.first, NULL, ob, ANIMTYPE_OBJECT, filter_mode, (ID *)ob); - } - } + ) } + /* ShapeKeys? */ if ((key) && !(ads->filterflag & ADS_FILTER_NOSHAPEKEYS)) { - /* Animation or Drivers */ - if ((ads->filterflag & ADS_FILTER_ONLYDRIVERS) == 0) { - /* 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++; + adt= key->adt; + ANIMDATA_FILTER_CASES(key, + { /* nla */ +#if 0 + /* include nla-expand widget? */ + if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) { + ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLNLA, base, ANIMTYPE_OBJECT, (ID *)ob); + if (ale) { + BLI_addtail(anim_data, ale); + items++; + } } - } - - /* add channels */ - if (FILTER_SKE_OBJD(key) || (filter_mode & ANIMFILTER_CURVESONLY)) { - items += animdata_filter_shapekey(anim_data, key, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob); - } - } - else { - /* Drivers */ - if (ANIMDATA_HAS_DRIVERS(key)) { - AnimData *adt= key->adt; +#endif + /* add NLA tracks */ + if (/*EXPANDED_NLTD(adt) ||*/ !(filter_mode & ANIMFILTER_CHANNELS)) + items += animdata_filter_nla(anim_data, adt->nla_tracks.first, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob); + }, + { /* drivers */ /* 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); @@ -985,15 +1066,28 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B } } - /* add F-Curve channels (drivers are F-Curves) */ - if (FILTER_SKE_OBJD(key)/*EXPANDED_DRVD(adt)*/ || !(filter_mode & ANIMFILTER_CHANNELS)) { - // XXX owner info is messed up now... - items += animdata_filter_fcurves(anim_data, adt->drivers.first, NULL, ob, ANIMTYPE_OBJECT, filter_mode, (ID *)key); + /* add channels */ + if (FILTER_SKE_OBJD(key) || (filter_mode & ANIMFILTER_CURVESONLY)) { + items += animdata_filter_shapekey(anim_data, key, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob); + } + }, + { /* 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++; + } + } + + /* add channels */ + if (FILTER_SKE_OBJD(key) || (filter_mode & ANIMFILTER_CURVESONLY)) { + items += animdata_filter_shapekey(anim_data, key, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob); } } - } + ) } - /* Materials? */ if ((ob->totcol) && !(ads->filterflag & ADS_FILTER_NOMAT)) @@ -1006,14 +1100,10 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B Camera *ca= (Camera *)ob->data; if ((ads->filterflag & ADS_FILTER_NOCAM) == 0) { - if ((ads->filterflag & ADS_FILTER_ONLYDRIVERS)==0) { - if (ANIMDATA_HAS_KEYS(ca)) - items += animdata_filter_dopesheet_obdata(anim_data, ads, base, filter_mode); - } - else { - if (ANIMDATA_HAS_DRIVERS(ca)) - items += animdata_filter_dopesheet_obdata(anim_data, ads, base, filter_mode); - } + ANIMDATA_FILTER_CASES(ca, + obdata_ok= 1;, + obdata_ok= 1;, + obdata_ok= 1;) } } break; @@ -1022,14 +1112,10 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B Lamp *la= (Lamp *)ob->data; if ((ads->filterflag & ADS_FILTER_NOLAM) == 0) { - if ((ads->filterflag & ADS_FILTER_ONLYDRIVERS)==0) { - if (ANIMDATA_HAS_KEYS(la)) - items += animdata_filter_dopesheet_obdata(anim_data, ads, base, filter_mode); - } - else { - if (ANIMDATA_HAS_DRIVERS(la)) - items += animdata_filter_dopesheet_obdata(anim_data, ads, base, filter_mode); - } + ANIMDATA_FILTER_CASES(la, + obdata_ok= 1;, + obdata_ok= 1;, + obdata_ok= 1;) } } break; @@ -1038,18 +1124,16 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B Curve *cu= (Curve *)ob->data; if ((ads->filterflag & ADS_FILTER_NOCUR) == 0) { - if ((ads->filterflag & ADS_FILTER_ONLYDRIVERS)==0) { - if (ANIMDATA_HAS_KEYS(cu)) - items += animdata_filter_dopesheet_obdata(anim_data, ads, base, filter_mode); - } - else { - if (ANIMDATA_HAS_DRIVERS(cu)) - items += animdata_filter_dopesheet_obdata(anim_data, ads, base, filter_mode); - } + ANIMDATA_FILTER_CASES(cu, + obdata_ok= 1;, + obdata_ok= 1;, + obdata_ok= 1;) } } break; } + if (obdata_ok) + items += animdata_filter_dopesheet_obdata(anim_data, ads, base, filter_mode); /* return the number of items added to the list */ return items; @@ -1058,6 +1142,7 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B static int animdata_filter_dopesheet_scene (ListBase *anim_data, bDopeSheet *ads, Scene *sce, int filter_mode) { World *wo= sce->world; + AnimData *adt= NULL; bAnimListElem *ale; int items = 0; @@ -1077,74 +1162,82 @@ static int animdata_filter_dopesheet_scene (ListBase *anim_data, bDopeSheet *ads if ( (EXPANDED_SCEC(sce) == 0) && !(filter_mode & ANIMFILTER_CURVESONLY) ) return items; - /* Action or Drivers */ - if ((ads->filterflag & ADS_FILTER_ONLYDRIVERS) == 0) { - /* Action? */ - if (ANIMDATA_HAS_KEYS(sce) && !(ads->filterflag & ADS_FILTER_NOSCE)) { - AnimData *adt= sce->adt; - - /* include action-expand widget? */ - if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) { - ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLACTD, sce, ANIMTYPE_SCENE, (ID *)sce); - if (ale) { - BLI_addtail(anim_data, ale); - items++; + /* Action, Drivers, or NLA for Scene */ + if ((ads->filterflag & ADS_FILTER_NOSCE) == 0) { + adt= sce->adt; + ANIMDATA_FILTER_CASES(sce, + { /* nla */ +#if 0 + /* include nla-expand widget? */ + if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) { + ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLNLA, base, ANIMTYPE_SCENE (ID *)sce); + if (ale) { + BLI_addtail(anim_data, ale); + items++; + } + } +#endif + + /* add NLA tracks */ + if (/*EXPANDED_NLTD(adt) ||*/ !(filter_mode & ANIMFILTER_CHANNELS)) + items += animdata_filter_nla(anim_data, adt->nla_tracks.first, filter_mode, sce, ANIMTYPE_SCENE, (ID *)sce); + }, + { /* drivers */ + /* include drivers-expand widget? */ + if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) { + ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLDRIVERS, sce, ANIMTYPE_SCENE, (ID *)sce); + if (ale) { + BLI_addtail(anim_data, ale); + items++; + } + } + + /* add F-Curve channels (drivers are F-Curves) */ + if (EXPANDED_DRVD(adt) || !(filter_mode & ANIMFILTER_CHANNELS)) { + items += animdata_filter_fcurves(anim_data, adt->drivers.first, NULL, sce, ANIMTYPE_SCENE, filter_mode, (ID *)sce); + } + }, + { /* action */ + /* include action-expand widget? */ + if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) { + ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLACTD, sce, ANIMTYPE_SCENE, (ID *)sce); + if (ale) { + BLI_addtail(anim_data, ale); + items++; + } + } + + /* add F-Curve channels? */ + if (EXPANDED_ACTC(adt->action) || !(filter_mode & ANIMFILTER_CHANNELS)) { + items += animdata_filter_action(anim_data, adt->action, filter_mode, sce, ANIMTYPE_SCENE, (ID *)sce); } } - - /* add F-Curve channels? */ - if (EXPANDED_ACTC(adt->action) || !(filter_mode & ANIMFILTER_CHANNELS)) { - items += animdata_filter_action(anim_data, adt->action, filter_mode, sce, ANIMTYPE_SCENE, (ID *)sce); - } - } + ) } - else { - /* Drivers */ - if (ANIMDATA_HAS_DRIVERS(sce) && !(ads->filterflag & ADS_FILTER_NOSCE)) { - AnimData *adt= sce->adt; - - /* include drivers-expand widget? */ - if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) { - ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLDRIVERS, sce, ANIMTYPE_SCENE, (ID *)sce); - if (ale) { - BLI_addtail(anim_data, ale); - items++; - } - } - - /* add F-Curve channels (drivers are F-Curves) */ - if (EXPANDED_DRVD(adt) || !(filter_mode & ANIMFILTER_CHANNELS)) { - items += animdata_filter_fcurves(anim_data, adt->drivers.first, NULL, sce, ANIMTYPE_SCENE, filter_mode, (ID *)sce); - } - } - } - + /* world */ if ((wo && wo->adt) && !(ads->filterflag & ADS_FILTER_NOWOR)) { - /* Animation or Drivers */ - if ((ads->filterflag & ADS_FILTER_ONLYDRIVERS) == 0) { - AnimData *adt= wo->adt; - - /* include world-expand widget? */ - if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) { - ale= make_new_animlistelem(wo, ANIMTYPE_DSWOR, sce, ANIMTYPE_SCENE, (ID *)sce); - if (ale) { - BLI_addtail(anim_data, ale); - items++; + /* Action, Drivers, or NLA for World */ + adt= wo->adt; + ANIMDATA_FILTER_CASES(wo, + { /* nla */ +#if 0 + /* include nla-expand widget? */ + if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) { + ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLNLA, base, ANIMTYPE_DSWOR (ID *)wo); + if (ale) { + BLI_addtail(anim_data, ale); + items++; + } } - } - - /* add channels */ - if (FILTER_WOR_SCED(wo) || (filter_mode & ANIMFILTER_CURVESONLY)) { - items += animdata_filter_action(anim_data, adt->action, filter_mode, wo, ANIMTYPE_DSWOR, (ID *)wo); - } - } - else { - /* Drivers */ - if (ANIMDATA_HAS_DRIVERS(wo)) { - AnimData *adt= wo->adt; +#endif - /* include shapekey-expand widget? */ + /* add NLA tracks */ + if (/*EXPANDED_NLTD(adt) ||*/ !(filter_mode & ANIMFILTER_CHANNELS)) + items += animdata_filter_nla(anim_data, adt->nla_tracks.first, filter_mode, wo, ANIMTYPE_DSWOR, (ID *)wo); + }, + { /* drivers */ + /* include world-expand widget? */ if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) { ale= make_new_animlistelem(wo, ANIMTYPE_DSWOR, sce, ANIMTYPE_SCENE, (ID *)wo); if (ale) { @@ -1158,8 +1251,23 @@ static int animdata_filter_dopesheet_scene (ListBase *anim_data, bDopeSheet *ads // XXX owner info is messed up now... items += animdata_filter_fcurves(anim_data, adt->drivers.first, NULL, wo, ANIMTYPE_DSWOR, filter_mode, (ID *)wo); } + }, + { /* action */ + /* include world-expand widget? */ + if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) { + ale= make_new_animlistelem(wo, ANIMTYPE_DSWOR, sce, ANIMTYPE_SCENE, (ID *)sce); + if (ale) { + BLI_addtail(anim_data, ale); + items++; + } + } + + /* add channels */ + if (FILTER_WOR_SCED(wo) || (filter_mode & ANIMFILTER_CURVESONLY)) { + items += animdata_filter_action(anim_data, adt->action, filter_mode, wo, ANIMTYPE_DSWOR, (ID *)wo); + } } - } + ) } /* return the number of items added to the list */ diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index efc0a0b9a57..75c10f957cc 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -75,8 +75,9 @@ typedef enum eAnimCont_Types { ANIMCONT_SHAPEKEY, /* shapekey (Key) */ ANIMCONT_GPENCIL, /* grease pencil (screen) */ ANIMCONT_DOPESHEET, /* dopesheet (bDopesheet) */ - ANIMCONT_FCURVES, /* animation F-Curves (bDopesheet) */ // XXX + ANIMCONT_FCURVES, /* animation F-Curves (bDopesheet) */ ANIMCONT_DRIVERS, /* drivers (bDopesheet) */ + ANIMCONT_NLA, /* nla (bDopesheet) */ } eAnimCont_Types; /* --------------- Channels -------------------- */ @@ -92,10 +93,10 @@ typedef struct bAnimListElem { int flag; /* copy of elem's flags for quick access */ int index; /* copy of adrcode where applicable */ - void *key_data; /* motion data - ipo or ipo-curve */ + void *key_data; /* motion data - mostly F-Curves, but can be other types too */ short datatype; /* type of motion data to expect */ - struct ID *id; /* ID block that channel is attached to (may be used */ + struct ID *id; /* ID block that channel is attached to (may be used */ void *owner; /* group or channel which acts as this channel's owner */ short ownertype; /* type of owner */ @@ -128,6 +129,8 @@ typedef enum eAnim_ChannelType { ANIMTYPE_GPDATABLOCK, ANIMTYPE_GPLAYER, + + ANIMTYPE_NLATRACK, } eAnim_ChannelType; /* types of keyframe data in bAnimListElem */ @@ -135,6 +138,7 @@ typedef enum eAnim_KeyType { ALE_NONE = 0, /* no keyframe data */ ALE_FCURVE, /* F-Curve */ ALE_GPFRAME, /* Grease Pencil Frames */ + ALE_NLASTRIP, /* NLA Strips */ // XXX the following are for summaries... should these be kept? ALE_SCE, /* Scene summary */ @@ -202,6 +206,10 @@ typedef enum eAnimFilter_Flags { #define EDITABLE_GPL(gpl) ((gpl->flag & GP_LAYER_LOCKED)==0) #define SEL_GPL(gpl) ((gpl->flag & GP_LAYER_ACTIVE) || (gpl->flag & GP_LAYER_SELECT)) +/* NLA only */ +#define SEL_NLT(nlt) (nlt->flag & NLATRACK_SELECTED) +#define EDITABLE_NLT(nlt) ((nlt->flag & NLATRACK_PROTECTED)==0) + /* -------------- Channel Defines -------------- */ /* channel heights */ diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c index 188315c73fb..cdaabe9e9de 100644 --- a/source/blender/editors/space_nla/space_nla.c +++ b/source/blender/editors/space_nla/space_nla.c @@ -72,6 +72,9 @@ static SpaceLink *nla_new(const bContext *C) snla= MEM_callocN(sizeof(SpaceNla), "initnla"); snla->spacetype= SPACE_NLA; + /* allocate DopeSheet data for NLA Editor */ + snla->ads= MEM_callocN(sizeof(bDopeSheet), "NLAEdit DopeSheet"); + /* header */ ar= MEM_callocN(sizeof(ARegion), "header for nla"); @@ -123,8 +126,12 @@ static SpaceLink *nla_new(const bContext *C) /* not spacelink itself */ static void nla_free(SpaceLink *sl) { -// SpaceNla *snla= (SpaceNla*) sl; + SpaceNla *snla= (SpaceNla*) sl; + if (snla->ads) { + BLI_freelistN(&snla->ads->chanbase); + MEM_freeN(snla->ads); + } } diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index cf54d69bb8b..9643e012ad4 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -287,6 +287,7 @@ typedef enum DOPESHEET_FILTERFLAG { /* general filtering */ ADS_FILTER_ONLYSEL = (1<<0), ADS_FILTER_ONLYDRIVERS = (1<<1), + ADS_FILTER_ONLYNLA = (1<<2), /* datatype-based filtering */ ADS_FILTER_NOSHAPEKEYS = (1<<6), diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 0a4fe1c5814..2dea6c4c969 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -244,10 +244,11 @@ typedef struct SpaceNla { short blockhandler[8]; - int filterflag; /* filtering flags (similar to the ones used for Keyframe Editors) */ short autosnap; /* this uses the same settings as autosnap for Action Editor */ short flag; + int pad; + struct bDopeSheet *ads; View2D v2d; /* depricated, copied to region */ } SpaceNla; From cee915ab56ebc02f246b12ff263f9a30edb1c5c4 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 29 May 2009 12:26:47 +0000 Subject: [PATCH 009/114] NLA SoC: Start of UI Drawing Code for NLA Editor In this commit, I've only setup the drawing code for the channels list. Only the drawing of the 'active action' dummy-line has been tested so far. --- source/blender/blenloader/intern/readfile.c | 2 +- .../blender/editors/animation/anim_filter.c | 75 ++- .../editors/animation/keyframes_draw.c | 2 - source/blender/editors/include/ED_anim_api.h | 1 + source/blender/editors/include/UI_view2d.h | 2 + source/blender/editors/interface/resources.c | 19 +- source/blender/editors/interface/view2d.c | 23 +- .../blender/editors/space_graph/space_graph.c | 2 +- source/blender/editors/space_nla/nla_draw.c | 480 ++++++++++++++++++ source/blender/editors/space_nla/nla_edit.c | 75 +++ source/blender/editors/space_nla/nla_header.c | 76 ++- source/blender/editors/space_nla/nla_intern.h | 22 + source/blender/editors/space_nla/space_nla.c | 184 ++++++- source/blender/makesdna/DNA_action_types.h | 11 +- 14 files changed, 902 insertions(+), 72 deletions(-) create mode 100644 source/blender/editors/space_nla/nla_draw.c create mode 100644 source/blender/editors/space_nla/nla_edit.c diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 192016f712d..2050e5da3ff 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -5680,7 +5680,7 @@ static void area_add_window_regions(ScrArea *sa, SpaceLink *sl, ListBase *lb) ar->v2d.scroll = (V2D_SCROLL_BOTTOM|V2D_SCROLL_SCALE_HORIZONTAL); ar->v2d.scroll |= (V2D_SCROLL_RIGHT); ar->v2d.keepzoom= V2D_LOCKZOOM_Y; - ar->v2d.align= V2D_ALIGN_NO_POS_Y; + ar->v2d.align= V2D_ALIGN_NO_NEG_Y; ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL; break; } diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index 69e4fbfb08e..f12e9a51f32 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -244,7 +244,7 @@ static short nlaedit_get_context (bAnimContext *ac, SpaceNla *snla) { /* init dopesheet data if non-existant (i.e. for old files) */ if (snla->ads == NULL) - snla->ads= MEM_callocN(sizeof(bDopeSheet), "GraphEdit DopeSheet"); + snla->ads= MEM_callocN(sizeof(bDopeSheet), "NlaEdit DopeSheet"); /* sync settings with current view status, then return appropriate data */ /* update scene-pointer (no need to check for pinning yet, as not implemented) */ @@ -359,6 +359,9 @@ short ANIM_animdata_get_context (const bContext *C, bAnimContext *ac) if (ANIMDATA_HAS_NLA(id)) {\ nlaOk\ }\ + else if (!(ads->filterflag & ADS_FILTER_NLA_NOACT) && ANIMDATA_HAS_KEYS(id)) {\ + nlaOk\ + }\ }\ else if (ads->filterflag & ADS_FILTER_ONLYDRIVERS) {\ if (ANIMDATA_HAS_DRIVERS(id)) {\ @@ -566,6 +569,13 @@ bAnimListElem *make_new_animlistelem (void *data, short datatype, void *owner, s ale->datatype= ALE_NLASTRIP; } break; + case ANIMTYPE_NLAACTION: + { + /* nothing to include for now... nothing editable from NLA-perspective here */ + ale->key_data= NULL; + ale->datatype= ALE_NONE; + } + break; } } @@ -594,7 +604,6 @@ static int animdata_filter_fcurves (ListBase *anim_data, FCurve *first, bActionG if ( ANIMCHANNEL_SELOK(SEL_FCU(fcu)) ) { /* only include if this curve is active */ if (!(filter_mode & ANIMFILTER_ACTIVE) || (fcu->flag & FCURVE_ACTIVE)) { - /* owner/ownertype will be either object or action-channel, depending if it was dopesheet or part of an action */ ale= make_new_animlistelem(fcu, ANIMTYPE_FCURVE, owner, ownertype, owner_id); if (ale) { @@ -682,10 +691,49 @@ static int animdata_filter_action (ListBase *anim_data, bAction *act, int filter return items; } -static int animdata_filter_nla (ListBase *anim_data, NlaTrack *first, int filter_mode, void *owner, short ownertype, ID *owner_id) +static int animdata_filter_nla (ListBase *anim_data, AnimData *adt, int filter_mode, void *owner, short ownertype, ID *owner_id) { - // FIXME - return 0; + bAnimListElem *ale; + NlaTrack *nlt; + int items = 0; + + /* loop over NLA Tracks - assume that the caller of this has already checked that these should be included */ + for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) { + /* only work with this channel and its subchannels if it is editable */ + if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_NLT(nlt)) { + /* only include this track if selected in a way consistent with the filtering requirements */ + if ( ANIMCHANNEL_SELOK(SEL_NLT(nlt)) ) { + /* only include if this track is active */ + // XXX keep this? + if (!(filter_mode & ANIMFILTER_ACTIVE) || (nlt->flag & NLATRACK_ACTIVE)) { + ale= make_new_animlistelem(nlt, ANIMTYPE_NLATRACK, owner, ownertype, owner_id); + + if (ale) { + BLI_addtail(anim_data, ale); + items++; + } + } + } + } + } + + /* if showing channels, include active action */ + if (filter_mode & ANIMFILTER_CHANNELS) { + /* there isn't really anything editable here, so skip if need editable */ + // TODO: currently, selection isn't checked since it doesn't matter + if ((filter_mode & ANIMFILTER_FOREDIT) == 0) { + /* just add the action track now */ + ale= make_new_animlistelem(adt->action, ANIMTYPE_NLAACTION, owner, ownertype, owner_id); + + if (ale) { + BLI_addtail(anim_data, ale); + items++; + } + } + } + + /* return the number of items added to the list */ + return items; } static int animdata_filter_shapekey (ListBase *anim_data, Key *key, int filter_mode, void *owner, short ownertype, ID *owner_id) @@ -881,7 +929,7 @@ static int animdata_filter_dopesheet_mats (ListBase *anim_data, bDopeSheet *ads, /* add material's animation data */ if (FILTER_MAT_OBJD(ma) || (filter_mode & ANIMFILTER_CURVESONLY)) { ANIMDATA_FILTER_CASES(ma, - items += animdata_filter_nla(anim_data, ma->adt->nla_tracks.first, filter_mode, ma, ANIMTYPE_DSMAT, (ID *)ma);, + items += animdata_filter_nla(anim_data, ma->adt, filter_mode, ma, ANIMTYPE_DSMAT, (ID *)ma);, items += animdata_filter_fcurves(anim_data, ma->adt->drivers.first, NULL, ma, ANIMTYPE_DSMAT, filter_mode, (ID *)ma);, items += animdata_filter_action(anim_data, ma->adt->action, filter_mode, ma, ANIMTYPE_DSMAT, (ID *)ma);) } @@ -946,7 +994,7 @@ static int animdata_filter_dopesheet_obdata (ListBase *anim_data, bDopeSheet *ad if ((expanded) || (filter_mode & ANIMFILTER_CURVESONLY)) { /* filtering for channels - nla, drivers, keyframes */ ANIMDATA_FILTER_CASES(iat, - items+= animdata_filter_nla(anim_data, iat->adt->nla_tracks.first, filter_mode, iat, type, (ID *)iat);, + items+= animdata_filter_nla(anim_data, iat->adt, filter_mode, iat, type, (ID *)iat);, items+= animdata_filter_fcurves(anim_data, adt->drivers.first, NULL, iat, type, filter_mode, (ID *)iat);, items += animdata_filter_action(anim_data, iat->adt->action, filter_mode, iat, type, (ID *)iat);) } @@ -997,8 +1045,7 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B #endif /* add NLA tracks */ - if (/*EXPANDED_NLTD(adt) ||*/ !(filter_mode & ANIMFILTER_CHANNELS)) - items += animdata_filter_nla(anim_data, adt->nla_tracks.first, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob); + items += animdata_filter_nla(anim_data, adt, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob); }, { /* drivers */ /* include drivers-expand widget? */ @@ -1053,8 +1100,7 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B #endif /* add NLA tracks */ - if (/*EXPANDED_NLTD(adt) ||*/ !(filter_mode & ANIMFILTER_CHANNELS)) - items += animdata_filter_nla(anim_data, adt->nla_tracks.first, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob); + items += animdata_filter_nla(anim_data, adt, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob); }, { /* drivers */ /* include shapekey-expand widget? */ @@ -1179,8 +1225,7 @@ static int animdata_filter_dopesheet_scene (ListBase *anim_data, bDopeSheet *ads #endif /* add NLA tracks */ - if (/*EXPANDED_NLTD(adt) ||*/ !(filter_mode & ANIMFILTER_CHANNELS)) - items += animdata_filter_nla(anim_data, adt->nla_tracks.first, filter_mode, sce, ANIMTYPE_SCENE, (ID *)sce); + items += animdata_filter_nla(anim_data, adt, filter_mode, sce, ANIMTYPE_SCENE, (ID *)sce); }, { /* drivers */ /* include drivers-expand widget? */ @@ -1233,8 +1278,7 @@ static int animdata_filter_dopesheet_scene (ListBase *anim_data, bDopeSheet *ads #endif /* add NLA tracks */ - if (/*EXPANDED_NLTD(adt) ||*/ !(filter_mode & ANIMFILTER_CHANNELS)) - items += animdata_filter_nla(anim_data, adt->nla_tracks.first, filter_mode, wo, ANIMTYPE_DSWOR, (ID *)wo); + items += animdata_filter_nla(anim_data, adt, filter_mode, wo, ANIMTYPE_DSWOR, (ID *)wo); }, { /* drivers */ /* include world-expand widget? */ @@ -1508,6 +1552,7 @@ int ANIM_animdata_filter (bAnimContext *ac, ListBase *anim_data, int filter_mode case ANIMCONT_DOPESHEET: case ANIMCONT_FCURVES: case ANIMCONT_DRIVERS: + case ANIMCONT_NLA: items= animdata_filter_dopesheet(anim_data, data, filter_mode); break; } diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c index cfbd6d2bced..144cd68f6df 100644 --- a/source/blender/editors/animation/keyframes_draw.c +++ b/source/blender/editors/animation/keyframes_draw.c @@ -412,8 +412,6 @@ void scene_to_keylist(Scene *sce, ListBase *keys, ListBase *blocks, ActKeysInc * /* get filterflag */ if (ads) filterflag= ads->filterflag; - else if ((aki) && (aki->actmode == -1)) /* only set like this by NLA */ - filterflag= ADS_FILTER_NLADUMMY; else filterflag= 0; diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index 75c10f957cc..7629fc29352 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -131,6 +131,7 @@ typedef enum eAnim_ChannelType { ANIMTYPE_GPLAYER, ANIMTYPE_NLATRACK, + ANIMTYPE_NLAACTION, } eAnim_ChannelType; /* types of keyframe data in bAnimListElem */ diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h index 7ff312151c5..c81ca909318 100644 --- a/source/blender/editors/include/UI_view2d.h +++ b/source/blender/editors/include/UI_view2d.h @@ -52,6 +52,8 @@ enum { V2D_COMMONVIEW_STANDARD, /* listview (i.e. Outliner) */ V2D_COMMONVIEW_LIST, + /* stackview (this is basically a list where new items are added at the top) */ + V2D_COMMONVIEW_STACK, /* headers (this is basically the same as listview, but no y-panning) */ V2D_COMMONVIEW_HEADER, /* ui region containing panels */ diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 1cb58c986d0..f0032809631 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -501,7 +501,10 @@ void ui_theme_init_userdef(void) btheme->tact= btheme->tipo; SETCOL(btheme->tact.strip, 12, 10, 10, 128); SETCOL(btheme->tact.strip_select, 255, 140, 0, 255); - + + /* space nla */ + btheme->tnla= btheme->tact; + /* space file */ /* to have something initialized */ btheme->tfile= btheme->tv3d; @@ -518,20 +521,6 @@ void ui_theme_init_userdef(void) SETCOL(btheme->tfile.scene, 250, 250, 250, 255); - - - /* space nla */ - btheme->tnla= btheme->tv3d; - SETCOL(btheme->tnla.back, 116, 116, 116, 255); - SETCOL(btheme->tnla.text, 0, 0, 0, 255); - SETCOL(btheme->tnla.text_hi, 255, 255, 255, 255); - SETCOL(btheme->tnla.grid, 94, 94, 94, 255); - SETCOL(btheme->tnla.shade1, 172, 172, 172, 255); // sliders - SETCOL(btheme->tnla.shade2, 84, 44, 31, 100); // bar - SETCOL(btheme->tnla.hilite, 17, 27, 60, 100); // bar - SETCOL(btheme->tnla.strip_select, 0xff, 0xff, 0xaa, 255); - SETCOL(btheme->tnla.strip, 0xe4, 0x9c, 0xc6, 255); - /* space seq */ btheme->tseq= btheme->tv3d; SETCOL(btheme->tseq.back, 116, 116, 116, 255); diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c index f2fc2deefbb..639f83d0d09 100644 --- a/source/blender/editors/interface/view2d.c +++ b/source/blender/editors/interface/view2d.c @@ -207,6 +207,23 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy) } break; + /* 'stack view' - practically the same as list/channel view, except is located in the pos y half instead. + * zoom, aspect ratio, and alignment restrictions are set here */ + case V2D_COMMONVIEW_STACK: + { + /* zoom + aspect ratio are locked */ + v2d->keepzoom = (V2D_LOCKZOOM_X|V2D_LOCKZOOM_Y|V2D_KEEPZOOM|V2D_KEEPASPECT); + v2d->minzoom= v2d->maxzoom= 1.0f; + + /* tot rect has strictly regulated placement, and must only occur in +/+ quadrant */ + v2d->align = (V2D_ALIGN_NO_NEG_X|V2D_ALIGN_NO_NEG_Y); + v2d->keeptot = V2D_KEEPTOT_STRICT; + tot_changed= 1; + + /* scroller settings are currently not set here... that is left for regions... */ + } + break; + /* 'header' regions - zoom, aspect ratio, alignment, and panning restrictions are set here */ case V2D_COMMONVIEW_HEADER: { @@ -245,14 +262,14 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy) v2d->tot.xmin= 0.0f; v2d->tot.xmax= winx; - + v2d->tot.ymax= 0.0f; v2d->tot.ymin= -winy; - + v2d->cur= v2d->tot; } break; - + /* other view types are completely defined using their own settings already */ default: /* we don't do anything here, as settings should be fine, but just make sure that rect */ diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c index 74002f64187..ef42b009bd4 100644 --- a/source/blender/editors/space_graph/space_graph.c +++ b/source/blender/editors/space_graph/space_graph.c @@ -192,7 +192,7 @@ static SpaceLink *graph_duplicate(SpaceLink *sl) SpaceIpo *sipon= MEM_dupallocN(sl); /* clear or remove stuff from old */ - //sipon->ipokey.first= sipon->ipokey.last= NULL; + BLI_duplicatelist(&sipon->ghostCurves, &((SpaceIpo *)sl)->ghostCurves); sipon->ads= MEM_dupallocN(sipon->ads); return (SpaceLink *)sipon; diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c new file mode 100644 index 00000000000..8b8ae7c5b8b --- /dev/null +++ b/source/blender/editors/space_nla/nla_draw.c @@ -0,0 +1,480 @@ +/** + * $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 + * All rights reserved. + * + * + * Contributor(s): Joshua Leung (major recode) + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include +#include +#include +#include + +#include "DNA_listBase.h" +#include "DNA_anim_types.h" +#include "DNA_action_types.h" +#include "DNA_armature_types.h" +#include "DNA_camera_types.h" +#include "DNA_curve_types.h" +#include "DNA_object_types.h" +#include "DNA_screen_types.h" +#include "DNA_scene_types.h" +#include "DNA_space_types.h" +#include "DNA_constraint_types.h" +#include "DNA_key_types.h" +#include "DNA_lamp_types.h" +#include "DNA_material_types.h" +#include "DNA_userdef_types.h" +#include "DNA_windowmanager_types.h" +#include "DNA_world_types.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" +#include "BLI_arithb.h" +#include "BLI_rand.h" + +#include "BKE_animsys.h" +#include "BKE_nla.h" +#include "BKE_context.h" +#include "BKE_screen.h" +#include "BKE_utildefines.h" + +#include "ED_anim_api.h" +#include "ED_space_api.h" +#include "ED_screen.h" + +#include "BIF_gl.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "UI_interface.h" +#include "UI_interface_icons.h" +#include "UI_resources.h" +#include "UI_view2d.h" + +#include "ED_markers.h" + +#include "nla_intern.h" // own include + +/* XXX */ +extern void gl_round_box(int mode, float minx, float miny, float maxx, float maxy, float rad); + +/* *********************************************** */ + +/* *********************************************** */ +/* Channel List */ + +void draw_nla_channel_list (bAnimContext *ac, SpaceNla *snla, ARegion *ar) +{ + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + View2D *v2d= &ar->v2d; + float x= 0.0f, y= 0.0f; + int items, height; + + /* build list of channels to draw */ + filter= (ANIMFILTER_VISIBLE|ANIMFILTER_CHANNELS); + items= ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + /* Update max-extent of channels here (taking into account scrollers): + * - this is done to allow the channel list to be scrollable, but must be done here + * to avoid regenerating the list again and/or also because channels list is drawn first + * - offset of NLACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for + * start of list offset, and the second is as a correction for the scrollers. + */ + height= ((items*NLACHANNEL_STEP) + (NLACHANNEL_HEIGHT*2)); + if (height > (v2d->mask.ymax - v2d->mask.ymin)) { + /* don't use totrect set, as the width stays the same + * (NOTE: this is ok here, the configuration is pretty straightforward) + */ + v2d->tot.ymax= (float)(height); + } + + /* loop through channels, and set up drawing depending on their type */ + y= (float)(-NLACHANNEL_FIRST); + + for (ale= anim_data.first; ale; ale= ale->next) { + const float yminc= (float)(y - NLACHANNEL_HEIGHT_HALF); + const float ymaxc= (float)(y + NLACHANNEL_HEIGHT_HALF); + const float ydatac= (float)(y - 7); + + /* check if visible */ + if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || + IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) + { + short indent= 0, offset= 0, sel= 0, group= 0; + int expand= -1, protect = -1, special= -1, mute = -1; + char name[128]; + + /* determine what needs to be drawn */ + switch (ale->type) { + case ANIMTYPE_SCENE: /* scene */ + { + Scene *sce= (Scene *)ale->data; + + group= 4; + indent= 0; + + special= ICON_SCENE_DATA; + + /* only show expand if there are any channels */ + if (EXPANDED_SCEC(sce)) + expand= ICON_TRIA_UP; + else + expand= ICON_TRIA_RIGHT; + + sel = SEL_SCEC(sce); + strcpy(name, sce->id.name+2); + } + break; + case ANIMTYPE_OBJECT: /* object */ + { + Base *base= (Base *)ale->data; + Object *ob= base->object; + + group= 4; + indent= 0; + + /* icon depends on object-type */ + if (ob->type == OB_ARMATURE) + special= ICON_ARMATURE_DATA; + else + special= ICON_OBJECT_DATA; + + /* only show expand if there are any channels */ + if (EXPANDED_OBJC(ob)) + expand= ICON_TRIA_UP; + else + expand= ICON_TRIA_RIGHT; + + sel = SEL_OBJC(base); + strcpy(name, ob->id.name+2); + } + break; + case ANIMTYPE_FILLMATD: /* object materials (dopesheet) expand widget */ + { + Object *ob = (Object *)ale->data; + + group = 4; + indent = 1; + special = ICON_MATERIAL_DATA; + + if (FILTER_MAT_OBJC(ob)) + expand = ICON_TRIA_UP; + else + expand = ICON_TRIA_RIGHT; + + strcpy(name, "Materials"); + } + break; + + + case ANIMTYPE_DSMAT: /* single material (dopesheet) expand widget */ + { + Material *ma = (Material *)ale->data; + + group = 0; + indent = 0; + special = ICON_MATERIAL_DATA; + offset = 21; + + if (FILTER_MAT_OBJD(ma)) + expand = ICON_TRIA_UP; + else + expand = ICON_TRIA_RIGHT; + + strcpy(name, ma->id.name+2); + } + break; + case ANIMTYPE_DSLAM: /* lamp (dopesheet) expand widget */ + { + Lamp *la = (Lamp *)ale->data; + + group = 4; + indent = 1; + special = ICON_LAMP_DATA; + + if (FILTER_LAM_OBJD(la)) + expand = ICON_TRIA_UP; + else + expand = ICON_TRIA_RIGHT; + + strcpy(name, la->id.name+2); + } + break; + case ANIMTYPE_DSCAM: /* camera (dopesheet) expand widget */ + { + Camera *ca = (Camera *)ale->data; + + group = 4; + indent = 1; + special = ICON_CAMERA_DATA; + + if (FILTER_CAM_OBJD(ca)) + expand = ICON_TRIA_UP; + else + expand = ICON_TRIA_RIGHT; + + strcpy(name, ca->id.name+2); + } + break; + case ANIMTYPE_DSCUR: /* curve (dopesheet) expand widget */ + { + Curve *cu = (Curve *)ale->data; + + group = 4; + indent = 1; + special = ICON_CURVE_DATA; + + if (FILTER_CUR_OBJD(cu)) + expand = ICON_TRIA_UP; + else + expand = ICON_TRIA_RIGHT; + + strcpy(name, cu->id.name+2); + } + break; + case ANIMTYPE_DSSKEY: /* shapekeys (dopesheet) expand widget */ + { + Key *key= (Key *)ale->data; + + group = 4; + indent = 1; + special = ICON_SHAPEKEY_DATA; // XXX + + if (FILTER_SKE_OBJD(key)) + expand = ICON_TRIA_UP; + else + expand = ICON_TRIA_RIGHT; + + //sel = SEL_OBJC(base); + strcpy(name, "Shape Keys"); + } + break; + case ANIMTYPE_DSWOR: /* world (dopesheet) expand widget */ + { + World *wo= (World *)ale->data; + + group = 4; + indent = 1; + special = ICON_WORLD_DATA; + + if (FILTER_WOR_SCED(wo)) + expand = ICON_TRIA_DOWN; + else + expand = ICON_TRIA_RIGHT; + + strcpy(name, wo->id.name+2); + } + break; + + case ANIMTYPE_NLATRACK: /* NLA Track */ + { + NlaTrack *nlt= (NlaTrack *)ale->data; + + indent= 0; + + if (ale->id) { + /* special exception for materials */ + if (GS(ale->id->name) == ID_MA) { + offset= 21; + indent= 1; + } + else + offset= 14; + } + else + offset= 0; + + /* FIXME: 'solo' as the 'special' button? + * - need special icons for these + */ + if (nlt->flag & NLATRACK_SOLO) + special= ICON_LAYER_ACTIVE; + else + special= ICON_LAYER_USED; + + if (nlt->flag & NLATRACK_MUTED) + mute = ICON_MUTE_IPO_ON; + else + mute = ICON_MUTE_IPO_OFF; + + if (EDITABLE_NLT(nlt)) + protect = ICON_UNLOCKED; + else + protect = ICON_LOCKED; + + strcpy(name, nlt->name); + } + break; + case ANIMTYPE_NLAACTION: /* NLA Action-Line */ + { + bAction *act= (bAction *)ale->data; + + group = 5; + + if (ale->id) { + /* special exception for materials */ + if (GS(ale->id->name) == ID_MA) { + offset= 21; + indent= 1; + } + else + offset= 14; + } + else + offset= 0; + + special = ICON_ACTION; + + if (act) + sprintf(name, "ActAction: <%s>", act->id.name+2); + else + sprintf(name, ""); + } + break; + } + + /* now, start drawing based on this information */ + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + + /* draw backing strip behind channel name */ + if (group == 4) { + /* only used in dopesheet... */ + if (ELEM(ale->type, ANIMTYPE_SCENE, ANIMTYPE_OBJECT)) { + /* object channel - darker */ + UI_ThemeColor(TH_DOPESHEET_CHANNELOB); + uiSetRoundBox((expand == ICON_TRIA_UP)? (8):(1|8)); + gl_round_box(GL_POLYGON, x+offset, yminc, (float)NLACHANNEL_NAMEWIDTH, ymaxc, 8); + } + else { + /* sub-object folders - lighter */ + UI_ThemeColor(TH_DOPESHEET_CHANNELSUBOB); + + offset += 7 * indent; + glBegin(GL_QUADS); + glVertex2f(x+offset, yminc); + glVertex2f(x+offset, ymaxc); + glVertex2f((float)ACHANNEL_NAMEWIDTH, ymaxc); + glVertex2f((float)ACHANNEL_NAMEWIDTH, yminc); + glEnd(); + + /* clear group value, otherwise we cause errors... */ + group = 0; + } + } + else if (group == 5) { + /* Action Line */ + if (ale->data) + glColor3f(0.8f, 0.2f, 0.0f); // reddish color - hardcoded for now + else + glColor3f(0.6f, 0.5f, 0.5f); // greyish-red color - hardcoded for now + + offset += 7 * indent; + uiSetRoundBox(15); + gl_round_box(GL_POLYGON, x+offset, yminc, (float)NLACHANNEL_NAMEWIDTH, ymaxc, 8); + + /* clear group value, otherwise we cause errors... */ + group = 0; + } + else { + /* for normal channels + * - use 3 shades of color group/standard color for 3 indention level + */ + UI_ThemeColorShade(TH_HEADER, ((indent==0)?20: (indent==1)?-20: -40)); + + indent += group; + offset += 7 * indent; + glBegin(GL_QUADS); + glVertex2f(x+offset, yminc); + glVertex2f(x+offset, ymaxc); + glVertex2f((float)NLACHANNEL_NAMEWIDTH, ymaxc); + glVertex2f((float)NLACHANNEL_NAMEWIDTH, yminc); + glEnd(); + } + + /* draw expand/collapse triangle */ + if (expand > 0) { + UI_icon_draw(x+offset, ydatac, expand); + offset += 17; + } + + /* draw special icon indicating certain data-types */ + if (special > -1) { + /* for normal channels */ + UI_icon_draw(x+offset, ydatac, special); + offset += 17; + } + glDisable(GL_BLEND); + + /* draw name */ + if (sel) + UI_ThemeColor(TH_TEXT_HI); + else + UI_ThemeColor(TH_TEXT); + offset += 3; + UI_DrawString(x+offset, y-4, name); + + /* reset offset - for RHS of panel */ + offset = 0; + + /* set blending again, as text drawing may clear it */ + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + + /* draw protect 'lock' */ + if (protect > -1) { + offset = 16; + UI_icon_draw((float)NLACHANNEL_NAMEWIDTH-offset, ydatac, protect); + } + + /* draw mute 'eye' */ + if (mute > -1) { + offset += 16; + UI_icon_draw((float)(NLACHANNEL_NAMEWIDTH-offset), ydatac, mute); + } + + /* draw action 'push-down' */ + if (ale->type == ANIMTYPE_NLAACTION) { + offset += 16; + UI_icon_draw((float)NLACHANNEL_NAMEWIDTH-offset, ydatac, ICON_FREEZE); + } + + glDisable(GL_BLEND); + } + + /* adjust y-position for next one */ + y += NLACHANNEL_STEP; + } + + /* free tempolary channels */ + BLI_freelistN(&anim_data); +} + +/* *********************************************** */ diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c new file mode 100644 index 00000000000..d9d0e5528ae --- /dev/null +++ b/source/blender/editors/space_nla/nla_edit.c @@ -0,0 +1,75 @@ +/** + * $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 + * All rights reserved. + * + * + * Contributor(s): Joshua Leung (major recode) + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include +#include + +#include "DNA_anim_types.h" +#include "DNA_action_types.h" +#include "DNA_nla_types.h" +#include "DNA_object_types.h" +#include "DNA_space_types.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" +#include "DNA_windowmanager_types.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" +#include "BLI_arithb.h" +#include "BLI_rand.h" + +#include "BKE_animsys.h" +#include "BKE_nla.h" +#include "BKE_context.h" +#include "BKE_report.h" +#include "BKE_screen.h" + +#include "ED_anim_api.h" +#include "ED_space_api.h" +#include "ED_screen.h" + +#include "BIF_gl.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "UI_interface.h" +#include "UI_resources.h" +#include "UI_view2d.h" + +#include "ED_markers.h" + +#include "nla_intern.h" // own include + +/* *********************************************** */ + + +/* *********************************************** */ + +/* *********************************************** */ diff --git a/source/blender/editors/space_nla/nla_header.c b/source/blender/editors/space_nla/nla_header.c index 0f6b77da6f5..0dcd3198db0 100644 --- a/source/blender/editors/space_nla/nla_header.c +++ b/source/blender/editors/space_nla/nla_header.c @@ -29,6 +29,10 @@ #include #include +#include "DNA_anim_types.h" +#include "DNA_action_types.h" +#include "DNA_nla_types.h" +#include "DNA_object_types.h" #include "DNA_space_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" @@ -37,26 +41,36 @@ #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" +#include "BLI_arithb.h" +#include "BLI_rand.h" +#include "BKE_animsys.h" +#include "BKE_nla.h" #include "BKE_context.h" +#include "BKE_report.h" #include "BKE_screen.h" - -#include "ED_screen.h" #include "ED_types.h" #include "ED_util.h" -#include "WM_api.h" -#include "WM_types.h" +#include "ED_anim_api.h" +#include "ED_space_api.h" +#include "ED_screen.h" #include "BIF_gl.h" -#include "BIF_glutil.h" + +#include "WM_api.h" +#include "WM_types.h" #include "UI_interface.h" #include "UI_resources.h" #include "UI_view2d.h" -#include "nla_intern.h" +#include "ED_markers.h" +/* button events */ +enum { + B_REDR = 0, +} eActHeader_ButEvents; /* ************************ header area region *********************** */ @@ -93,13 +107,17 @@ static uiBlock *dummy_viewmenu(bContext *C, ARegion *ar, void *arg_unused) static void do_nla_buttons(bContext *C, void *arg, int event) { - switch(event) { + switch (event) { + case B_REDR: + ED_area_tag_redraw(CTX_wm_area(C)); + break; } } void nla_header_buttons(const bContext *C, ARegion *ar) { + SpaceNla *snla= (SpaceNla *)CTX_wm_space_data(C); ScrArea *sa= CTX_wm_area(C); uiBlock *block; int xco, yco= 3; @@ -109,7 +127,7 @@ void nla_header_buttons(const bContext *C, ARegion *ar) xco= ED_area_header_standardbuttons(C, block, yco); - if((sa->flag & HEADER_NO_PULLDOWN)==0) { + if ((sa->flag & HEADER_NO_PULLDOWN)==0) { int xmax; xmax= GetButStringLength("View"); @@ -119,7 +137,47 @@ 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"); + uiBlockEndAlign(block); + xco += 15; + } + else { + // XXX this case shouldn't happen at all... for now, just pad out same amount of space + xco += 7*XIC + 15; + } + xco += (XIC + 8); + + /* auto-snap selector */ + if (snla->flag & SNLA_DRAWTIME) { + uiDefButS(block, MENU, B_REDR, + "Auto-Snap Keyframes %t|No Time-Snap %x0|Nearest Second %x2|Nearest Marker %x3", + xco,yco,90,YIC, &snla->autosnap, 0, 1, 0, 0, + "Auto-snapping mode for times when transforming"); + } + else { + uiDefButS(block, MENU, B_REDR, + "Auto-Snap Keyframes %t|No Time-Snap %x0|Nearest Frame %x2|Nearest Marker %x3", + xco,yco,90,YIC, &snla->autosnap, 0, 1, 0, 0, + "Auto-snapping mode for times when transforming"); + } + xco += 98; + /* always as last */ UI_view2d_totRect_set(&ar->v2d, xco+XIC+80, ar->v2d.tot.ymax-ar->v2d.tot.ymin); diff --git a/source/blender/editors/space_nla/nla_intern.h b/source/blender/editors/space_nla/nla_intern.h index c544bd9a408..4d013db8be9 100644 --- a/source/blender/editors/space_nla/nla_intern.h +++ b/source/blender/editors/space_nla/nla_intern.h @@ -30,8 +30,30 @@ /* internal exports only */ +/* -------------- NLA Channel Defines -------------- */ +/* NLA channel heights */ +#define NLACHANNEL_FIRST -16 +#define NLACHANNEL_HEIGHT 24 +#define NLACHANNEL_HEIGHT_HALF 12 +#define NLACHANNEL_SKIP 2 +#define NLACHANNEL_STEP (NLACHANNEL_HEIGHT + NLACHANNEL_SKIP) + +/* channel widths */ +#define NLACHANNEL_NAMEWIDTH 200 + +/* channel toggle-buttons */ +#define NLACHANNEL_BUTTON_WIDTH 16 + + +/* **************************************** */ +/* nla_draw.c */ + +void draw_nla_channel_list(bAnimContext *ac, SpaceNla *snla, ARegion *ar); + +/* **************************************** */ /* nla_header.c */ + void nla_header_buttons(const bContext *C, ARegion *ar); diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c index cdaabe9e9de..39888162a95 100644 --- a/source/blender/editors/space_nla/space_nla.c +++ b/source/blender/editors/space_nla/space_nla.c @@ -42,10 +42,16 @@ #include "BLI_arithb.h" #include "BLI_rand.h" +#include "BKE_animsys.h" +#include "BKE_action.h" +#include "BKE_nla.h" #include "BKE_colortools.h" #include "BKE_context.h" #include "BKE_screen.h" +#include "BKE_utildefines.h" +#include "ED_anim_api.h" +#include "ED_markers.h" #include "ED_space_api.h" #include "ED_screen.h" @@ -58,8 +64,6 @@ #include "UI_resources.h" #include "UI_view2d.h" -#include "ED_markers.h" - #include "nla_intern.h" // own include /* ******************** default callbacks for nla space ***************** */ @@ -73,7 +77,7 @@ static SpaceLink *nla_new(const bContext *C) snla->spacetype= SPACE_NLA; /* allocate DopeSheet data for NLA Editor */ - snla->ads= MEM_callocN(sizeof(bDopeSheet), "NLAEdit DopeSheet"); + snla->ads= MEM_callocN(sizeof(bDopeSheet), "NlaEdit DopeSheet"); /* header */ ar= MEM_callocN(sizeof(ARegion), "header for nla"); @@ -82,13 +86,15 @@ static SpaceLink *nla_new(const bContext *C) ar->regiontype= RGN_TYPE_HEADER; ar->alignment= RGN_ALIGN_BOTTOM; - /* channel list region XXX */ - ar= MEM_callocN(sizeof(ARegion), "area region from do_versions"); + /* channel list region */ + ar= MEM_callocN(sizeof(ARegion), "channel list for nla"); BLI_addtail(&snla->regionbase, ar); ar->regiontype= RGN_TYPE_CHANNELS; ar->alignment= RGN_ALIGN_LEFT; - ar->v2d.scroll = (V2D_SCROLL_RIGHT|V2D_SCROLL_BOTTOM); + /* only need to set these settings since this will use the 'stack' configuration */ + ar->v2d.scroll = V2D_SCROLL_BOTTOM; + ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL; /* main area */ ar= MEM_callocN(sizeof(ARegion), "main area for nla"); @@ -115,10 +121,11 @@ static SpaceLink *nla_new(const bContext *C) ar->v2d.minzoom= 0.1f; ar->v2d.maxzoom= 50.0f; - ar->v2d.scroll |= (V2D_SCROLL_BOTTOM|V2D_SCROLL_SCALE_HORIZONTAL); + ar->v2d.scroll = (V2D_SCROLL_BOTTOM|V2D_SCROLL_SCALE_HORIZONTAL); ar->v2d.scroll |= (V2D_SCROLL_RIGHT); ar->v2d.keepzoom= V2D_LOCKZOOM_Y; - + ar->v2d.align= V2D_ALIGN_NO_NEG_Y; + ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL; return (SpaceLink *)snla; } @@ -138,7 +145,13 @@ static void nla_free(SpaceLink *sl) /* spacetype; init callback */ static void nla_init(struct wmWindowManager *wm, ScrArea *sa) { + SpaceNla *snla= (SpaceNla *)sa->spacedata.first; + + /* init dopesheet data if non-existant (i.e. for old files) */ + if (snla->ads == NULL) + snla->ads= MEM_callocN(sizeof(bDopeSheet), "NlaEdit DopeSheet"); + ED_area_tag_refresh(sa); } static SpaceLink *nla_duplicate(SpaceLink *sl) @@ -146,15 +159,31 @@ static SpaceLink *nla_duplicate(SpaceLink *sl) SpaceNla *snlan= MEM_dupallocN(sl); /* clear or remove stuff from old */ + snlan->ads= MEM_dupallocN(snlan->ads); return (SpaceLink *)snlan; } +/* add handlers, stuff you only do once or on area/region changes */ +static void nla_channel_area_init(wmWindowManager *wm, ARegion *ar) +{ + //ListBase *keymap; + + UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_STACK, ar->winx, ar->winy); + + /* own keymap */ + // TODO: cannot use generic copy, need special NLA version + //keymap= WM_keymap_listbase(wm, "Animation_Channels", 0, 0); /* XXX weak? */ + //WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); +} + +/* draw entirely, view changes should be handled here */ static void nla_channel_area_draw(const bContext *C, ARegion *ar) { - /* draw entirely, view changes should be handled here */ - // SpaceNla *snla= (SpaceNla*)CTX_wm_space_data(C); - // View2D *v2d= &ar->v2d; + SpaceNla *snla= (SpaceNla*)CTX_wm_space_data(C); + bAnimContext ac; + View2D *v2d= &ar->v2d; + View2DScrollers *scrollers; float col[3]; /* clear and setup matrix */ @@ -162,15 +191,20 @@ static void nla_channel_area_draw(const bContext *C, ARegion *ar) glClearColor(col[0], col[1], col[2], 0.0); glClear(GL_COLOR_BUFFER_BIT); - // UI_view2d_view_ortho(C, v2d); - - /* data... */ + UI_view2d_view_ortho(C, v2d); + /* data */ + if (ANIM_animdata_get_context(C, &ac)) { + draw_nla_channel_list(&ac, snla, ar); + } /* reset view matrix */ - //UI_view2d_view_restore(C); + UI_view2d_view_restore(C); - /* scrollers? */ + /* scrollers */ + scrollers= UI_view2d_scrollers_calc(C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY); + UI_view2d_scrollers_draw(C, v2d, scrollers); + UI_view2d_scrollers_free(scrollers); } @@ -189,9 +223,13 @@ static void nla_main_area_init(wmWindowManager *wm, ARegion *ar) static void nla_main_area_draw(const bContext *C, ARegion *ar) { /* draw entirely, view changes should be handled here */ - // SpaceNla *snla= (SpaceNla*)CTX_wm_space_data(C); + SpaceNla *snla= (SpaceNla*)CTX_wm_space_data(C); + bAnimContext ac; View2D *v2d= &ar->v2d; + View2DGrid *grid; + View2DScrollers *scrollers; float col[3]; + short unit=0, flag=0; /* clear and setup matrix */ UI_GetThemeColor3fv(TH_BACK, col); @@ -199,14 +237,38 @@ static void nla_main_area_draw(const bContext *C, ARegion *ar) glClear(GL_COLOR_BUFFER_BIT); UI_view2d_view_ortho(C, v2d); - - /* data... */ + /* time grid */ + unit= (snla->flag & SNLA_DRAWTIME)? V2D_UNIT_SECONDS : V2D_UNIT_FRAMES; + grid= UI_view2d_grid_calc(C, v2d, unit, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY, ar->winx, ar->winy); + UI_view2d_grid_draw(C, v2d, grid, V2D_GRIDLINES_ALL); + UI_view2d_grid_free(grid); + + /* data */ + if (ANIM_animdata_get_context(C, &ac)) { + //draw_channel_strips(&ac, saction, ar); + } + + /* current frame */ + if (snla->flag & SNLA_DRAWTIME) flag |= DRAWCFRA_UNIT_SECONDS; + if ((snla->flag & SNLA_NODRAWCFRANUM)==0) flag |= DRAWCFRA_SHOW_NUMBOX; + ANIM_draw_cfra(C, v2d, flag); + + /* markers */ + UI_view2d_view_orthoSpecial(C, v2d, 1); + draw_markers_time(C, 0); + + /* preview range */ + UI_view2d_view_ortho(C, v2d); + ANIM_draw_previewrange(C, v2d); /* reset view matrix */ UI_view2d_view_restore(C); - /* scrollers? */ + /* scrollers */ + scrollers= UI_view2d_scrollers_calc(C, v2d, unit, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY); + UI_view2d_scrollers_draw(C, v2d, scrollers); + UI_view2d_scrollers_free(scrollers); } void nla_operatortypes(void) @@ -250,6 +312,82 @@ static void nla_header_area_draw(const bContext *C, ARegion *ar) static void nla_main_area_listener(ARegion *ar, wmNotifier *wmn) { /* context changes */ + switch(wmn->category) { + case NC_SCENE: + switch(wmn->data) { + case ND_OB_ACTIVE: + case ND_FRAME: + case ND_MARKERS: + ED_region_tag_redraw(ar); + break; + } + break; + case NC_OBJECT: + switch(wmn->data) { + case ND_BONE_ACTIVE: + case ND_BONE_SELECT: + case ND_KEYS: + case ND_TRANSFORM: + ED_region_tag_redraw(ar); + break; + } + break; + default: + if(wmn->data==ND_KEYS) + ED_region_tag_redraw(ar); + } +} + +static void nla_channel_area_listener(ARegion *ar, wmNotifier *wmn) +{ + /* context changes */ + switch(wmn->category) { + case NC_SCENE: + switch(wmn->data) { + case ND_OB_ACTIVE: + ED_region_tag_redraw(ar); + break; + } + break; + case NC_OBJECT: + switch(wmn->data) { + case ND_BONE_ACTIVE: + case ND_BONE_SELECT: + case ND_KEYS: + ED_region_tag_redraw(ar); + break; + } + break; + default: + if(wmn->data==ND_KEYS) + ED_region_tag_redraw(ar); + } +} + +/* editor level listener */ +static void nla_listener(ScrArea *sa, wmNotifier *wmn) +{ + /* context changes */ + switch (wmn->category) { + case NC_SCENE: + /*switch (wmn->data) { + case ND_OB_ACTIVE: + case ND_OB_SELECT: + ED_area_tag_refresh(sa); + break; + }*/ + ED_area_tag_refresh(sa); + break; + case NC_OBJECT: + /*switch (wmn->data) { + case ND_BONE_SELECT: + case ND_BONE_ACTIVE: + ED_area_tag_refresh(sa); + break; + }*/ + ED_area_tag_refresh(sa); + break; + } } /* only called once, from space/spacetypes.c */ @@ -265,6 +403,7 @@ void ED_spacetype_nla(void) st->init= nla_init; st->duplicate= nla_duplicate; st->operatortypes= nla_operatortypes; + st->listener= nla_listener; st->keymap= nla_keymap; /* regions: main window */ @@ -273,7 +412,7 @@ void ED_spacetype_nla(void) art->init= nla_main_area_init; art->draw= nla_main_area_draw; art->listener= nla_main_area_listener; - art->keymapflag= ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES; + art->keymapflag= ED_KEYMAP_VIEW2D/*|ED_KEYMAP_MARKERS*/|ED_KEYMAP_ANIMATION|ED_KEYMAP_FRAMES; BLI_addhead(&st->regiontypes, art); @@ -294,8 +433,9 @@ void ED_spacetype_nla(void) art->minsizex= 200; art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D; - //art->init= nla_channel_area_init; + art->init= nla_channel_area_init; art->draw= nla_channel_area_draw; + art->listener= nla_channel_area_listener; BLI_addhead(&st->regiontypes, art); diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index 802f8d88c03..e41ab5ac492 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -288,9 +288,10 @@ typedef struct bDopeSheet { /* DopeSheet filter-flag */ typedef enum DOPESHEET_FILTERFLAG { /* general filtering */ - ADS_FILTER_ONLYSEL = (1<<0), - ADS_FILTER_ONLYDRIVERS = (1<<1), - ADS_FILTER_ONLYNLA = (1<<2), + ADS_FILTER_ONLYSEL = (1<<0), /* only include channels relating to selected data */ + + ADS_FILTER_ONLYDRIVERS = (1<<1), /* for 'Drivers' editor - only include Driver data from AnimData */ + ADS_FILTER_ONLYNLA = (1<<2), /* for 'NLA' editor - only include NLA data from AnimData */ /* datatype-based filtering */ ADS_FILTER_NOSHAPEKEYS = (1<<6), @@ -301,9 +302,11 @@ typedef enum DOPESHEET_FILTERFLAG { ADS_FILTER_NOWOR = (1<<14), ADS_FILTER_NOSCE = (1<<15), + /* 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_NLADUMMY = (ADS_FILTER_NOSHAPEKEYS|ADS_FILTER_NOOBDATA), } DOPESHEET_FILTERFLAG; /* DopeSheet general flags */ From 72205f45e4e4dfd14460d693ccda30f7677ae9be Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sat, 30 May 2009 00:28:33 +0000 Subject: [PATCH 010/114] NLA SoC: Basic Strip drawing Implemented some basic strip-drawing code with some hardcoded colours. These colours will be made into theme colours at some point, but the aim is to use different colours as indicators of the 'state' of the strip (i.e. active/being tweaked, uses the same action as the strip being tweaked, selected, normal). This is not yet usable though... --- source/blender/editors/space_nla/nla_draw.c | 138 ++++++++++++++++++ source/blender/editors/space_nla/nla_intern.h | 1 + source/blender/editors/space_nla/nla_ops.c | 121 +++++++++++++++ source/blender/editors/space_nla/space_nla.c | 2 +- source/blender/makesdna/DNA_anim_types.h | 2 + 5 files changed, 263 insertions(+), 1 deletion(-) create mode 100644 source/blender/editors/space_nla/nla_ops.c diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index 8b8ae7c5b8b..8da59ced436 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -83,6 +83,144 @@ extern void gl_round_box(int mode, float minx, float miny, float maxx, float maxy, float rad); /* *********************************************** */ +/* Strips */ + +static void nla_draw_strip (NlaTrack *nlt, NlaStrip *strip, View2D *v2d, float yminc, float ymaxc) +{ + /* draw extrapolation info first (as backdrop) */ + // TODO... + + /* draw 'inside' of strip itself */ + /* set color of strip - color is used to indicate status here */ + if (strip->flag & NLASTRIP_FLAG_ACTIVE) { + /* tweaking strip should be drawn green when it is acting as the tweaking strip */ + // FIXME: hardcoded temp-hack colors + glColor3f(0.3f, 0.95f, 0.1f); + } + else if (strip->flag & NLASTRIP_FLAG_TWEAKUSER) { + /* alert user that this strip is also used by the tweaking track (this is set when going into + * 'editmode' for that strip), since the edits made here may not be what the user anticipated + */ + // FIXME: hardcoded temp-hack colors + glColor3f(0.85f, 0.0f, 0.0f); + } + else if (strip->flag & NLASTRIP_FLAG_SELECT) { + /* selected strip - use theme color for selected */ + UI_ThemeColor(TH_STRIP_SELECT); + } + else { + /* normal, unselected strip - use standard strip theme color */ + UI_ThemeColor(TH_STRIP); + } + uiSetRoundBox(15); /* all corners rounded */ + gl_round_box(GL_POLYGON, strip->start, yminc, strip->end, ymaxc, 9); + + /* draw strip outline */ + if (strip->flag & NLASTRIP_FLAG_ACTIVE) { + /* strip should appear 'sunken', so draw a light border around it */ + glColor3f(0.9f, 1.0f, 0.9f); // FIXME: hardcoded temp-hack colors + } + else { + /* strip should appear to stand out, so draw a dark border around it */ + glColor3f(0.0f, 0.0f, 0.0f); + } + gl_round_box(GL_LINES, strip->start, yminc, strip->end, ymaxc, 9); +} + +/* ---------------------- */ + +void draw_nla_main_data (bAnimContext *ac, SpaceNla *snla, ARegion *ar) +{ + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + View2D *v2d= &ar->v2d; + float y= 0.0f; + int items, height; + + /* build list of channels to draw */ + filter= (ANIMFILTER_VISIBLE|ANIMFILTER_CHANNELS); + items= ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + /* Update max-extent of channels here (taking into account scrollers): + * - this is done to allow the channel list to be scrollable, but must be done here + * to avoid regenerating the list again and/or also because channels list is drawn first + * - offset of NLACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for + * start of list offset, and the second is as a correction for the scrollers. + */ + height= ((items*NLACHANNEL_STEP) + (NLACHANNEL_HEIGHT*2)); + if (height > (v2d->mask.ymax - v2d->mask.ymin)) { + /* don't use totrect set, as the width stays the same + * (NOTE: this is ok here, the configuration is pretty straightforward) + */ + v2d->tot.ymax= (float)(height); + } + + /* loop through channels, and set up drawing depending on their type */ + y= (float)(-NLACHANNEL_FIRST); + + for (ale= anim_data.first; ale; ale= ale->next) { + const float yminc= (float)(y - NLACHANNEL_HEIGHT_HALF); + const float ymaxc= (float)(y + NLACHANNEL_HEIGHT_HALF); + + /* check if visible */ + if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || + IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) + { + /* data to draw depends on the type of channel */ + switch (ale->type) { + case ANIMTYPE_NLATRACK: + { + NlaTrack *nlt= (NlaTrack *)ale->data; + NlaStrip *strip; + + /* draw backdrop? */ + // TODO... + + /* draw each strip in the track */ + for (strip= nlt->strips.first; strip; strip= strip->next) { + /* only draw if at least part of the strip is within view */ + if ( IN_RANGE(v2d->cur.xmin, strip->start, strip->end) || + IN_RANGE(v2d->cur.xmax, strip->start, strip->end) ) + { + nla_draw_strip(nlt, strip, v2d, yminc, ymaxc); + } + } + } + break; + + case ANIMTYPE_NLAACTION: + { + /* just draw a semi-shaded rect spanning the width of the viewable area if there's data */ + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + + if (ale->data) + glColor4f(0.8f, 0.2f, 0.0f, 0.4f); // reddish color - hardcoded for now + else + glColor4f(0.6f, 0.5f, 0.5f, 0.3f); // greyish-red color - hardcoded for now + + glBegin(GL_QUADS); + glVertex2f(v2d->cur.xmin, yminc); + glVertex2f(v2d->cur.xmin, ymaxc); + glVertex2f(v2d->cur.xmax, ymaxc); + glVertex2f(v2d->cur.xmax, yminc); + glEnd(); + + glDisable(GL_BLEND); + } + break; + } + } + + /* adjust y-position for next one */ + y += NLACHANNEL_STEP; + } + + /* free tempolary channels */ + BLI_freelistN(&anim_data); +} /* *********************************************** */ /* Channel List */ diff --git a/source/blender/editors/space_nla/nla_intern.h b/source/blender/editors/space_nla/nla_intern.h index 4d013db8be9..3728ba2cbc8 100644 --- a/source/blender/editors/space_nla/nla_intern.h +++ b/source/blender/editors/space_nla/nla_intern.h @@ -49,6 +49,7 @@ /* **************************************** */ /* nla_draw.c */ +void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar); void draw_nla_channel_list(bAnimContext *ac, SpaceNla *snla, ARegion *ar); /* **************************************** */ diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c new file mode 100644 index 00000000000..f0e3bd5bca5 --- /dev/null +++ b/source/blender/editors/space_nla/nla_ops.c @@ -0,0 +1,121 @@ +/** + * $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 + * All rights reserved. + * + * + * Contributor(s): Joshua Leung (major recode) + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include +#include + +#include "DNA_anim_types.h" +#include "DNA_action_types.h" +#include "DNA_nla_types.h" +#include "DNA_object_types.h" +#include "DNA_space_types.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" +#include "DNA_windowmanager_types.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" +#include "BLI_arithb.h" +#include "BLI_rand.h" + +#include "BKE_animsys.h" +#include "BKE_nla.h" +#include "BKE_context.h" +#include "BKE_report.h" +#include "BKE_screen.h" + +#include "ED_anim_api.h" +#include "ED_space_api.h" +#include "ED_screen.h" + +#include "BIF_gl.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "UI_interface.h" +#include "UI_resources.h" +#include "UI_view2d.h" + +#include "ED_markers.h" + +#include "nla_intern.h" // own include + + +/* ************************** registration - operator types **********************************/ + +void nla_operatortypes(void) +{ + //WM_operatortype_append(); + +} + +/* ************************** registration - keymaps **********************************/ + +static void nla_keymap_channels (wmWindowManager *wm, ListBase *keymap) +{ + //wmKeymapItem *kmi; + + + + /* transform system */ + //transform_keymap_for_space(wm, keymap, SPACE_NLA); +} + +static void nla_keymap_main (wmWindowManager *wm, ListBase *keymap) +{ + //wmKeymapItem *kmi; + + + + /* transform system */ + //transform_keymap_for_space(wm, keymap, SPACE_NLA); +} + +/* --------------- */ + +void nla_keymap(wmWindowManager *wm) +{ + ListBase *keymap; + + /* channels */ + /* Channels are not directly handled by the NLA Editor module, but are inherited from the Animation module. + * Most of the relevant operations, keymaps, drawing, etc. can therefore all be found in that module instead, as there + * are many similarities with the other Animation Editors. + * + * 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); + nla_keymap_channels(wm, keymap); + + /* data */ + keymap= WM_keymap_listbase(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 39888162a95..bf122227a8b 100644 --- a/source/blender/editors/space_nla/space_nla.c +++ b/source/blender/editors/space_nla/space_nla.c @@ -246,7 +246,7 @@ static void nla_main_area_draw(const bContext *C, ARegion *ar) /* data */ if (ANIM_animdata_get_context(C, &ac)) { - //draw_channel_strips(&ac, saction, ar); + draw_nla_main_data(&ac, snla, ar); } /* current frame */ diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h index b20ec7ba37f..fe535b671f8 100644 --- a/source/blender/makesdna/DNA_anim_types.h +++ b/source/blender/makesdna/DNA_anim_types.h @@ -444,6 +444,8 @@ enum { NLASTRIP_FLAG_SELECT = (1<<1), // NLASTRIP_FLAG_SELECT_L = (1<<2), // left handle selected // NLASTRIP_FLAG_SELECT_R = (1<<3), // right handle selected + /* NLA strip uses the same action that the action being tweaked uses (not set for the twaking one though) */ + NLASTRIP_FLAG_TWEAKUSER = (1<<4), /* controls driven by local F-Curves */ /* strip influence is controlled by local F-Curve */ From 32d0533f78c63d5d95b693e1e6e65144203dc42a Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sat, 30 May 2009 10:41:41 +0000 Subject: [PATCH 011/114] NLA SoC: More UI work + 'Push down' tool 'UI Work' * Added more drawing code for drawing NLA data * Made the operators for the 'channel-list' of NLA work. A special version of borderselect for the NLA channel-list (due to the different vertical order) still needs to be coded though. 'Push Down' tool The active action of each AnimData block, represented by the reddy/orange channel, can be added to the NLA stack as a new action by using the 'snow-flake' icon/button (probably need a special icon for this later). This will add a new NLA track and an NLA strip referencing this action. The AnimData block's 'active action' slot will then be left empty. (Unfortunately, there still seems to be a bug here, which I'll check on later) --- .../blender/editors/animation/anim_channels.c | 12 + .../blender/editors/space_nla/nla_channels.c | 336 ++++++++++++++++++ source/blender/editors/space_nla/nla_draw.c | 28 +- source/blender/editors/space_nla/nla_edit.c | 7 +- source/blender/editors/space_nla/nla_intern.h | 17 + source/blender/editors/space_nla/nla_ops.c | 44 ++- source/blender/editors/space_nla/space_nla.c | 17 +- 7 files changed, 431 insertions(+), 30 deletions(-) create mode 100644 source/blender/editors/space_nla/nla_channels.c diff --git a/source/blender/editors/animation/anim_channels.c b/source/blender/editors/animation/anim_channels.c index 9e0e50a8de5..a5f2acb591c 100644 --- a/source/blender/editors/animation/anim_channels.c +++ b/source/blender/editors/animation/anim_channels.c @@ -217,6 +217,10 @@ void ANIM_deselect_anim_channels (void *data, short datatype, short test, short if (ale->flag & FCURVE_SELECTED) sel= ACHANNEL_SETFLAG_CLEAR; break; + case ANIMTYPE_NLATRACK: + if (ale->flag & NLATRACK_SELECTED) + sel= ACHANNEL_SETFLAG_CLEAR; + break; } } } @@ -263,6 +267,14 @@ void ANIM_deselect_anim_channels (void *data, short datatype, short test, short fcu->flag &= ~FCURVE_ACTIVE; } break; + case ANIMTYPE_NLATRACK: + { + NlaTrack *nlt= (NlaTrack *)ale->data; + + ACHANNEL_SET_FLAG(nlt, sel, NLATRACK_SELECTED); + nlt->flag &= ~NLATRACK_ACTIVE; + } + break; } } diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c new file mode 100644 index 00000000000..658ce69cc10 --- /dev/null +++ b/source/blender/editors/space_nla/nla_channels.c @@ -0,0 +1,336 @@ +/** + * $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 + * All rights reserved. + * + * + * Contributor(s): Joshua Leung (major recode) + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include +#include +#include +#include + +#include "DNA_listBase.h" +#include "DNA_anim_types.h" +#include "DNA_action_types.h" +#include "DNA_armature_types.h" +#include "DNA_camera_types.h" +#include "DNA_curve_types.h" +#include "DNA_object_types.h" +#include "DNA_screen_types.h" +#include "DNA_scene_types.h" +#include "DNA_space_types.h" +#include "DNA_key_types.h" +#include "DNA_lamp_types.h" +#include "DNA_material_types.h" +#include "DNA_userdef_types.h" +#include "DNA_windowmanager_types.h" +#include "DNA_world_types.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" +#include "BLI_arithb.h" +#include "BLI_rand.h" + +#include "BKE_animsys.h" +#include "BKE_nla.h" +#include "BKE_context.h" +#include "BKE_screen.h" +#include "BKE_utildefines.h" + +#include "ED_anim_api.h" +#include "ED_keyframes_edit.h" +#include "ED_markers.h" +#include "ED_space_api.h" +#include "ED_screen.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "UI_interface.h" +#include "UI_interface_icons.h" +#include "UI_resources.h" +#include "UI_view2d.h" + +#include "nla_intern.h" // own include + +/* *********************************************** */ +/* Operators for NLA channels-list which need to be different from the standard Animation Editor ones */ + +// TODO: implemented borderselect too, since that also relies on ranges of buttons + +/* ******************** Mouse-Click Operator *********************** */ +/* Depending on the channel that was clicked on, the mouse click will activate whichever + * part of the channel is relevant. + * + * NOTE: eventually, this should probably be phased out when many of these things are replaced with buttons + */ + +static void mouse_nla_channels (bAnimContext *ac, float x, int channel_index, short selectmode) +{ + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + /* get the channel that was clicked on */ + /* filter channels */ + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CHANNELS); + filter= ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + /* get channel from index */ + ale= BLI_findlink(&anim_data, channel_index); + if (ale == NULL) { + /* channel not found */ + printf("Error: animation channel (index = %d) not found in mouse_anim_channels() \n", channel_index); + + BLI_freelistN(&anim_data); + return; + } + + /* action to take depends on what channel we've got */ + switch (ale->type) { + case ANIMTYPE_SCENE: + { + Scene *sce= (Scene *)ale->data; + + if (x < 16) { + /* toggle expand */ + sce->flag ^= SCE_DS_COLLAPSED; + } + else { + /* set selection status */ + if (selectmode == SELECT_INVERT) { + /* swap select */ + sce->flag ^= SCE_DS_SELECTED; + } + else { + sce->flag |= SCE_DS_SELECTED; + } + } + } + break; + case ANIMTYPE_OBJECT: + { + bDopeSheet *ads= (bDopeSheet *)ac->data; + Scene *sce= (Scene *)ads->source; + Base *base= (Base *)ale->data; + Object *ob= base->object; + + if (x < 16) { + /* toggle expand */ + ob->nlaflag ^= OB_ADS_COLLAPSED; // XXX + } + else { + /* set selection status */ + if (selectmode == SELECT_INVERT) { + /* swap select */ + base->flag ^= SELECT; + ob->flag= base->flag; + } + else { + Base *b; + + /* deleselect all */ + for (b= sce->base.first; b; b= b->next) { + b->flag &= ~SELECT; + b->object->flag= b->flag; + } + + /* select object now */ + base->flag |= SELECT; + ob->flag |= SELECT; + } + + /* xxx should be ED_base_object_activate(), but we need context pointer for that... */ + //set_active_base(base); + } + } + break; + case ANIMTYPE_FILLMATD: + { + Object *ob= (Object *)ale->data; + ob->nlaflag ^= OB_ADS_SHOWMATS; // XXX + } + break; + + case ANIMTYPE_DSMAT: + { + Material *ma= (Material *)ale->data; + ma->flag ^= MA_DS_EXPAND; + } + break; + case ANIMTYPE_DSLAM: + { + Lamp *la= (Lamp *)ale->data; + la->flag ^= LA_DS_EXPAND; + } + break; + case ANIMTYPE_DSCAM: + { + Camera *ca= (Camera *)ale->data; + ca->flag ^= CAM_DS_EXPAND; + } + break; + case ANIMTYPE_DSCUR: + { + Curve *cu= (Curve *)ale->data; + cu->flag ^= CU_DS_EXPAND; + } + break; + case ANIMTYPE_DSSKEY: + { + Key *key= (Key *)ale->data; + key->flag ^= KEYBLOCK_DS_EXPAND; + } + break; + case ANIMTYPE_DSWOR: + { + World *wo= (World *)ale->data; + wo->flag ^= WO_DS_EXPAND; + } + break; + + case ANIMTYPE_NLATRACK: + { + NlaTrack *nlt= (NlaTrack *)ale->data; + + if (x >= (NLACHANNEL_NAMEWIDTH-NLACHANNEL_BUTTON_WIDTH)) { + /* toggle protection (only if there's a toggle there) */ + nlt->flag ^= NLATRACK_PROTECTED; + } + else if (x >= (NLACHANNEL_NAMEWIDTH-2*NLACHANNEL_BUTTON_WIDTH)) { + /* toggle mute */ + nlt->flag ^= NLATRACK_MUTED; + } + else { + /* set selection */ + if (selectmode == SELECT_INVERT) { + /* inverse selection status of this F-Curve only */ + nlt->flag ^= NLATRACK_SELECTED; + } + else { + /* select F-Curve by itself */ + ANIM_deselect_anim_channels(ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR); + nlt->flag |= NLATRACK_SELECTED; + } + + /* if NLA-Track is selected now, make NLA-Track the 'active' one in the visible list */ + if (nlt->flag & NLATRACK_SELECTED) + ANIM_set_active_channel(ac->data, ac->datatype, filter, nlt, ANIMTYPE_NLATRACK); + } + } + break; + case ANIMTYPE_NLAACTION: + { + AnimData *adt= BKE_animdata_from_id(ale->owner); /* this won't crash, right? */ + + /* for now, only do something if user clicks on the 'push-down' button */ + if (x >= (NLACHANNEL_NAMEWIDTH-NLACHANNEL_BUTTON_WIDTH)) { + /* activate push-down operator */ + // TODO: make this use the operator instead of calling the function directly + // however, calling the operator requires that we supply the args, and that works with proper buttons only + BKE_nla_action_pushdown(adt); + } + } + break; + + default: + printf("Error: Invalid channel type in mouse_nla_channels() \n"); + } + + /* free channels */ + BLI_freelistN(&anim_data); +} + +/* ------------------- */ + +/* handle clicking */ +static int nlachannels_mouseclick_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + bAnimContext ac; + Scene *scene; + ARegion *ar; + View2D *v2d; + int mval[2], channel_index; + short selectmode; + float x, y; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* get useful pointers from animation context data */ + scene= ac.scene; + ar= ac.ar; + v2d= &ar->v2d; + + /* get mouse coordinates (in region coordinates) */ + mval[0]= (event->x - ar->winrct.xmin); + mval[1]= (event->y - ar->winrct.ymin); + + /* select mode is either replace (deselect all, then add) or add/extend */ + if (RNA_boolean_get(op->ptr, "extend")) + selectmode= SELECT_INVERT; + else + selectmode= SELECT_REPLACE; + + /* figure out which channel user clicked in + * Note: although channels technically start at y= ACHANNEL_FIRST, we need to adjust by half a channel's height + * so that the tops of channels get caught ok. Since NLACHANNEL_FIRST is really NLACHANNEL_HEIGHT, we simply use + * NLACHANNEL_HEIGHT_HALF. + */ + UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y); + UI_view2d_listview_view_to_cell(v2d, NLACHANNEL_NAMEWIDTH, NLACHANNEL_STEP, 0, (float)NLACHANNEL_HEIGHT_HALF, x, y, NULL, &channel_index); + + /* handle mouse-click in the relevant channel then */ + mouse_nla_channels(&ac, x, channel_index, selectmode); + + /* set notifier tha things have changed */ + ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_CHANNELS); + + return OPERATOR_FINISHED; +} + +void NLA_OT_channels_click (wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Mouse Click on Channels"; + ot->idname= "NLA_OT_channels_click"; + + /* api callbacks */ + ot->invoke= nlachannels_mouseclick_invoke; + ot->poll= ED_operator_areaactive; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* id-props */ + RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); // SHIFTKEY +} + +/* *********************************************** */ diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index 8da59ced436..081064317d6 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -85,8 +85,10 @@ extern void gl_round_box(int mode, float minx, float miny, float maxx, float max /* *********************************************** */ /* Strips */ -static void nla_draw_strip (NlaTrack *nlt, NlaStrip *strip, View2D *v2d, float yminc, float ymaxc) +static void nla_draw_strip (NlaTrack *nlt, NlaStrip *strip, int index, View2D *v2d, float yminc, float ymaxc) { + char name[128]; + /* draw extrapolation info first (as backdrop) */ // TODO... @@ -125,6 +127,15 @@ static void nla_draw_strip (NlaTrack *nlt, NlaStrip *strip, View2D *v2d, float y glColor3f(0.0f, 0.0f, 0.0f); } gl_round_box(GL_LINES, strip->start, yminc, strip->end, ymaxc, 9); + + /* draw some identifying info on the strip (index and name of action if there's room) */ + // XXX for now, just the index + if (strip->flag & NLASTRIP_FLAG_SELECT) + UI_ThemeColor(TH_TEXT_HI); + else + UI_ThemeColor(TH_TEXT); + sprintf(name, "%d |", index); + UI_DrawString(strip->start, yminc+8, name); } /* ---------------------- */ @@ -174,17 +185,18 @@ void draw_nla_main_data (bAnimContext *ac, SpaceNla *snla, ARegion *ar) { NlaTrack *nlt= (NlaTrack *)ale->data; NlaStrip *strip; + int index; /* draw backdrop? */ // TODO... /* draw each strip in the track */ - for (strip= nlt->strips.first; strip; strip= strip->next) { + for (strip=nlt->strips.first, index=1; strip; strip= strip->next, index++) { /* only draw if at least part of the strip is within view */ if ( IN_RANGE(v2d->cur.xmin, strip->start, strip->end) || IN_RANGE(v2d->cur.xmax, strip->start, strip->end) ) { - nla_draw_strip(nlt, strip, v2d, yminc, ymaxc); + nla_draw_strip(nlt, strip, index, v2d, yminc, ymaxc); } } } @@ -601,6 +613,16 @@ void draw_nla_channel_list (bAnimContext *ac, SpaceNla *snla, ARegion *ar) /* draw action 'push-down' */ if (ale->type == ANIMTYPE_NLAACTION) { offset += 16; + + /* XXX firstly draw a little rect to help identify that it's different from the toggles */ + glBegin(GL_LINES); + glVertex2f((float)NLACHANNEL_NAMEWIDTH-offset-1, y-7); + glVertex2f((float)NLACHANNEL_NAMEWIDTH-offset-1, y+7); + glVertex2f((float)NLACHANNEL_NAMEWIDTH-1, y-7; + glVertex2f((float)NLACHANNEL_NAMEWIDTH-1, y+7); + glEnd(); // GL_LINES + + /* now draw the icon */ UI_icon_draw((float)NLACHANNEL_NAMEWIDTH-offset, ydatac, ICON_FREEZE); } diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index d9d0e5528ae..ce9ae7de7a9 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -51,10 +51,12 @@ #include "BKE_screen.h" #include "ED_anim_api.h" +#include "ED_markers.h" #include "ED_space_api.h" #include "ED_screen.h" -#include "BIF_gl.h" +#include "RNA_access.h" +#include "RNA_define.h" #include "WM_api.h" #include "WM_types.h" @@ -63,13 +65,10 @@ #include "UI_resources.h" #include "UI_view2d.h" -#include "ED_markers.h" - #include "nla_intern.h" // own include /* *********************************************** */ - /* *********************************************** */ /* *********************************************** */ diff --git a/source/blender/editors/space_nla/nla_intern.h b/source/blender/editors/space_nla/nla_intern.h index 3728ba2cbc8..37eb7774696 100644 --- a/source/blender/editors/space_nla/nla_intern.h +++ b/source/blender/editors/space_nla/nla_intern.h @@ -57,6 +57,23 @@ void draw_nla_channel_list(bAnimContext *ac, SpaceNla *snla, ARegion *ar); void nla_header_buttons(const bContext *C, ARegion *ar); +/* **************************************** */ +/* nla_select.c */ + + +/* **************************************** */ +/* nla_edit.c */ + +/* **************************************** */ +/* nla_channels.c */ + +void NLA_OT_channels_click(wmOperatorType *ot); + +/* **************************************** */ +/* nla_ops.c */ + +void nla_operatortypes(void); +void nla_keymap(wmWindowManager *wm); #endif /* ED_NLA_INTERN_H */ diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c index f0e3bd5bca5..ea450a08475 100644 --- a/source/blender/editors/space_nla/nla_ops.c +++ b/source/blender/editors/space_nla/nla_ops.c @@ -54,17 +54,15 @@ #include "ED_space_api.h" #include "ED_screen.h" -#include "BIF_gl.h" - #include "WM_api.h" #include "WM_types.h" +#include "RNA_access.h" + #include "UI_interface.h" #include "UI_resources.h" #include "UI_view2d.h" -#include "ED_markers.h" - #include "nla_intern.h" // own include @@ -72,20 +70,46 @@ void nla_operatortypes(void) { - //WM_operatortype_append(); + /* channels */ + WM_operatortype_append(NLA_OT_channels_click); + /* select */ + // ... } /* ************************** registration - keymaps **********************************/ static void nla_keymap_channels (wmWindowManager *wm, ListBase *keymap) { - //wmKeymapItem *kmi; + /* NLA-specific (different to standard channels keymap) -------------------------- */ + /* selection */ + /* click-select */ + // XXX for now, only leftmouse.... + WM_keymap_add_item(keymap, "NLA_OT_channels_click", LEFTMOUSE, KM_PRESS, 0, 0); + RNA_boolean_set(WM_keymap_add_item(keymap, "NLA_OT_channels_click", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "extend", 1); + /* General Animation Channels keymap (see anim_channels.c) ----------------------- */ + /* deselect all */ + WM_keymap_add_item(keymap, "ANIM_OT_channels_select_all_toggle", AKEY, KM_PRESS, 0, 0); + RNA_boolean_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_select_all_toggle", IKEY, KM_PRESS, KM_CTRL, 0)->ptr, "invert", 1); + /* borderselect */ + WM_keymap_add_item(keymap, "ANIM_OT_channels_select_border", BKEY, KM_PRESS, 0, 0); - /* transform system */ - //transform_keymap_for_space(wm, keymap, SPACE_NLA); + /* settings */ + WM_keymap_add_item(keymap, "ANIM_OT_channels_setting_toggle", WKEY, KM_PRESS, KM_SHIFT, 0); + WM_keymap_add_item(keymap, "ANIM_OT_channels_setting_enable", WKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0); + WM_keymap_add_item(keymap, "ANIM_OT_channels_setting_disable", WKEY, KM_PRESS, KM_ALT, 0); + + /* settings - specialised hotkeys */ + WM_keymap_add_item(keymap, "ANIM_OT_channels_editable_toggle", TABKEY, KM_PRESS, 0, 0); + + /* expand/collapse */ + WM_keymap_add_item(keymap, "ANIM_OT_channels_expand", PADPLUSKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "ANIM_OT_channels_collapse", PADMINUS, KM_PRESS, 0, 0); + + RNA_boolean_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_expand", PADPLUSKEY, KM_PRESS, KM_CTRL, 0)->ptr, "all", 1); + 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) @@ -111,11 +135,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_listbase(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_listbase(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 bf122227a8b..1313b4d915d 100644 --- a/source/blender/editors/space_nla/space_nla.c +++ b/source/blender/editors/space_nla/space_nla.c @@ -167,14 +167,14 @@ 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; + ListBase *keymap; UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_STACK, ar->winx, ar->winy); /* own keymap */ // TODO: cannot use generic copy, need special NLA version - //keymap= WM_keymap_listbase(wm, "Animation_Channels", 0, 0); /* XXX weak? */ - //WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); + keymap= WM_keymap_listbase(wm, "NLA Channels", SPACE_NLA, 0); /* XXX weak? */ + WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); } /* draw entirely, view changes should be handled here */ @@ -216,7 +216,7 @@ static void nla_main_area_init(wmWindowManager *wm, ARegion *ar) UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy); /* own keymap */ - keymap= WM_keymap_listbase(wm, "NLA", SPACE_NLA, 0); /* XXX weak? */ + keymap= WM_keymap_listbase(wm, "NLA Data", SPACE_NLA, 0); /* XXX weak? */ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); } @@ -271,15 +271,6 @@ static void nla_main_area_draw(const bContext *C, ARegion *ar) UI_view2d_scrollers_free(scrollers); } -void nla_operatortypes(void) -{ - -} - -void nla_keymap(struct wmWindowManager *wm) -{ - -} /* add handlers, stuff you only do once or on area/region changes */ static void nla_header_area_init(wmWindowManager *wm, ARegion *ar) From aa4d64d7ff17d4557acd74540914de872a32ba81 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sat, 30 May 2009 11:05:29 +0000 Subject: [PATCH 012/114] NLA SoC: Bugfixes for previous commit * Compile fix in nla_draw.c * Not totally correct yet, but now NLA-tracks get drawn too after action 'push-down' --- source/blender/blenkernel/intern/nla.c | 11 ++- .../blender/editors/animation/anim_filter.c | 77 +++++++++---------- source/blender/editors/space_nla/nla_draw.c | 2 +- 3 files changed, 46 insertions(+), 44 deletions(-) diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index d062a2ab14b..3356f599c59 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -427,8 +427,10 @@ void BKE_nla_action_pushdown (AnimData *adt) * as that will cause us grief down the track */ // TODO: what about modifiers? - if (action_has_motion(adt->action) == 0) + if (action_has_motion(adt->action) == 0) { + printf("BKE_nla_action_pushdown(): action has no data \n"); return; + } /* add a new NLA track to house this action * - we could investigate trying to fit the action into an appropriately @@ -436,8 +438,10 @@ void BKE_nla_action_pushdown (AnimData *adt) * changes in blending behaviour... */ nlt= add_nlatrack(adt); - if (nlt == NULL) + if (nlt == NULL) { + printf("BKE_nla_action_pushdown(): no NLA-track added \n"); return; + } /* add a new NLA strip to the track, which references the active action */ strip= add_nlastrip(nlt, adt->action); @@ -448,6 +452,9 @@ void BKE_nla_action_pushdown (AnimData *adt) adt->action= NULL; } + // TEMP DEBUG... + printf("BKE_nla_action_pushdown(): NLA strip added.. done \n"); + // TODO: set any other flags necessary here... } diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index f12e9a51f32..f1f2a31b9b1 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -1334,22 +1334,18 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int /* scene-linked animation */ // TODO: sequencer, composite nodes - are we to include those here too? { - short sceOk, worOk; + short sceOk= 0, worOk= 0; /* check filtering-flags if ok */ - if (ads->filterflag) { - if (ads->filterflag & ADS_FILTER_ONLYDRIVERS) { - sceOk= (ANIMDATA_HAS_DRIVERS(sce) && !(ads->filterflag & ADS_FILTER_NOSCE)); - worOk= ((sce->world) && ANIMDATA_HAS_DRIVERS(sce->world) && !(ads->filterflag & ADS_FILTER_NOWOR)); - } - else { - sceOk= (ANIMDATA_HAS_KEYS(sce) && !(ads->filterflag & ADS_FILTER_NOSCE)); - worOk= ((sce->world) && ANIMDATA_HAS_KEYS(sce->world) && !(ads->filterflag & ADS_FILTER_NOWOR)); - } - } - else { - sceOk= (ANIMDATA_HAS_KEYS(sce)); - worOk= ((sce->world) && ANIMDATA_HAS_KEYS(sce->world)); + ANIMDATA_FILTER_CASES(sce, + sceOk= !(ads->filterflag & ADS_FILTER_NOSCE);, + sceOk= !(ads->filterflag & ADS_FILTER_NOSCE);, + sceOk= !(ads->filterflag & ADS_FILTER_NOSCE);) + if (sce->world) { + ANIMDATA_FILTER_CASES(sce->world, + worOk= !(ads->filterflag & ADS_FILTER_NOWOR);, + worOk= !(ads->filterflag & ADS_FILTER_NOWOR);, + worOk= !(ads->filterflag & ADS_FILTER_NOWOR);) } /* check if not all bad (i.e. so there is something to show) */ @@ -1391,13 +1387,17 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int } /* check filters for datatypes */ - if (ads->filterflag & ADS_FILTER_ONLYDRIVERS) { - actOk= (ANIMDATA_HAS_DRIVERS(ob)); - keyOk= ((key) && ANIMDATA_HAS_DRIVERS(key) && !(ads->filterflag & ADS_FILTER_NOSHAPEKEYS)); - } - else { - actOk= ANIMDATA_HAS_KEYS(ob); - keyOk= ((key) && ANIMDATA_HAS_KEYS(key) && !(ads->filterflag & ADS_FILTER_NOSHAPEKEYS)); + /* object */ + ANIMDATA_FILTER_CASES(ob, + actOk= 1;, + actOk= 1;, + actOk= 1;) + if (key) { + /* shapekeys */ + ANIMDATA_FILTER_CASES(key, + keyOk= 1;, + keyOk= 1;, + keyOk= 1;) } /* materials - only for geometric types */ @@ -1412,18 +1412,13 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int Material *ma= give_current_material(ob, a); /* if material has relevant animation data, break */ - if (ads->filterflag & ADS_FILTER_ONLYDRIVERS) { - if (ANIMDATA_HAS_DRIVERS(ma)) { - matOk= 1; - break; - } - } - else { - if (ANIMDATA_HAS_KEYS(ma)) { - matOk= 1; - break; - } - } + ANIMDATA_FILTER_CASES(ma, + matOk= 1;, + matOk= 1;, + matOk= 1;) + + if (matOk) + break; } } @@ -1432,19 +1427,19 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int case OB_CAMERA: /* ------- Camera ------------ */ { Camera *ca= (Camera *)ob->data; - if (ads->filterflag & ADS_FILTER_ONLYDRIVERS) - dataOk= (ANIMDATA_HAS_DRIVERS(ca) && !(ads->filterflag & ADS_FILTER_NOCAM)); - else - dataOk= (ANIMDATA_HAS_KEYS(ca) && !(ads->filterflag & ADS_FILTER_NOCAM)); + ANIMDATA_FILTER_CASES(ca, + dataOk= !(ads->filterflag & ADS_FILTER_NOCAM);, + dataOk= !(ads->filterflag & ADS_FILTER_NOCAM);, + dataOk= !(ads->filterflag & ADS_FILTER_NOCAM);) } break; case OB_LAMP: /* ---------- Lamp ----------- */ { Lamp *la= (Lamp *)ob->data; - if (ads->filterflag & ADS_FILTER_ONLYDRIVERS) - dataOk= (ANIMDATA_HAS_DRIVERS(la) && !(ads->filterflag & ADS_FILTER_NOLAM)); - else - dataOk= (ANIMDATA_HAS_KEYS(la) && !(ads->filterflag & ADS_FILTER_NOLAM)); + ANIMDATA_FILTER_CASES(la, + dataOk= !(ads->filterflag & ADS_FILTER_NOLAM);, + dataOk= !(ads->filterflag & ADS_FILTER_NOLAM);, + dataOk= !(ads->filterflag & ADS_FILTER_NOLAM);) } break; default: /* --- other --- */ diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index 081064317d6..8ff9522358c 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -618,7 +618,7 @@ void draw_nla_channel_list (bAnimContext *ac, SpaceNla *snla, ARegion *ar) glBegin(GL_LINES); glVertex2f((float)NLACHANNEL_NAMEWIDTH-offset-1, y-7); glVertex2f((float)NLACHANNEL_NAMEWIDTH-offset-1, y+7); - glVertex2f((float)NLACHANNEL_NAMEWIDTH-1, y-7; + glVertex2f((float)NLACHANNEL_NAMEWIDTH-1, y-7); glVertex2f((float)NLACHANNEL_NAMEWIDTH-1, y+7); glEnd(); // GL_LINES From 2e85686fe379f99c27944e3e4b5842d89e620f3b Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sat, 30 May 2009 12:40:07 +0000 Subject: [PATCH 013/114] NLA SoC: Fixes (UI, evaluation?) * Fixed some bugs which meant that NLA-strips weren't getting drawn * Removed some debugging code * Fixed bug with Action-line disappearing after 'pushing down' actions * Fixed bug where Objects with no animation data showed up in NLA * Tried fixing a bug where NLA-strips were evaluated erratically. I have a feeling that there are some rounding errors I'll need to pay more attention to somewhere :/ --- source/blender/blenkernel/intern/anim_sys.c | 6 +- source/blender/blenkernel/intern/nla.c | 3 - .../blender/editors/animation/anim_filter.c | 12 +++- source/blender/editors/space_nla/nla_draw.c | 63 ++++++++++--------- 4 files changed, 47 insertions(+), 37 deletions(-) diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index f21fed416cc..652f733d553 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -627,14 +627,14 @@ static float nlastrip_get_influence (NlaStrip *strip, float cframe) strip->blendout= (float)fabs(strip->blendout); /* result depends on where frame is in respect to blendin/out values */ - // TODO: are the fabs() tests needed here? + // the +0.0001 factors are to combat rounding errors if (IS_EQ(strip->blendin, 0)==0 && (cframe <= (strip->start + strip->blendin))) { /* there is some blend-in */ - return (float)fabs(cframe - strip->start) / (strip->blendin); + return (float)(fabs(cframe - strip->start) + 0.0001) / (strip->blendin); } else if (IS_EQ(strip->blendout, 0)==0 && (cframe >= (strip->end - strip->blendout))) { /* there is some blend-out */ - return (float)fabs(strip->end - cframe) / (strip->blendout); + return (float)(fabs(strip->end - cframe) + 0.0001) / (strip->blendout); } else { /* in the middle of the strip, we should be full strength */ diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 3356f599c59..62500af85ff 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -452,9 +452,6 @@ void BKE_nla_action_pushdown (AnimData *adt) adt->action= NULL; } - // TEMP DEBUG... - printf("BKE_nla_action_pushdown(): NLA strip added.. done \n"); - // TODO: set any other flags necessary here... } diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index f1f2a31b9b1..ed526bd99a0 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -722,8 +722,12 @@ static int animdata_filter_nla (ListBase *anim_data, AnimData *adt, int filter_m /* there isn't really anything editable here, so skip if need editable */ // TODO: currently, selection isn't checked since it doesn't matter if ((filter_mode & ANIMFILTER_FOREDIT) == 0) { - /* just add the action track now */ - ale= make_new_animlistelem(adt->action, ANIMTYPE_NLAACTION, owner, ownertype, owner_id); + /* just add the action track now (this MUST appear for drawing) + * - as AnimData may not have an action, we pass a dummy pointer just to get the list elem created, then + * overwrite this with the real value - REVIEW THIS... + */ + ale= make_new_animlistelem((void *)(&adt->action), ANIMTYPE_NLAACTION, owner, ownertype, owner_id); + ale->data= (adt->action) ? adt->action : NULL; if (ale) { BLI_addtail(anim_data, ale); @@ -1388,6 +1392,8 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int /* check filters for datatypes */ /* object */ + actOk= 0; + keyOk= 0; ANIMDATA_FILTER_CASES(ob, actOk= 1;, actOk= 1;, @@ -1427,6 +1433,7 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int case OB_CAMERA: /* ------- Camera ------------ */ { Camera *ca= (Camera *)ob->data; + dataOk= 0; ANIMDATA_FILTER_CASES(ca, dataOk= !(ads->filterflag & ADS_FILTER_NOCAM);, dataOk= !(ads->filterflag & ADS_FILTER_NOCAM);, @@ -1436,6 +1443,7 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int case OB_LAMP: /* ---------- Lamp ----------- */ { Lamp *la= (Lamp *)ob->data; + dataOk= 0; ANIMDATA_FILTER_CASES(la, dataOk= !(ads->filterflag & ADS_FILTER_NOLAM);, dataOk= !(ads->filterflag & ADS_FILTER_NOLAM);, diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index 8ff9522358c..28572704302 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -81,14 +81,13 @@ /* XXX */ extern void gl_round_box(int mode, float minx, float miny, float maxx, float maxy, float rad); +extern void gl_round_box_shade(int mode, float minx, float miny, float maxx, float maxy, float rad, float shadetop, float shadedown); /* *********************************************** */ /* Strips */ -static void nla_draw_strip (NlaTrack *nlt, NlaStrip *strip, int index, View2D *v2d, float yminc, float ymaxc) +static void nla_draw_strip (NlaTrack *nlt, NlaStrip *strip, View2D *v2d, float yminc, float ymaxc) { - char name[128]; - /* draw extrapolation info first (as backdrop) */ // TODO... @@ -115,7 +114,7 @@ static void nla_draw_strip (NlaTrack *nlt, NlaStrip *strip, int index, View2D *v UI_ThemeColor(TH_STRIP); } uiSetRoundBox(15); /* all corners rounded */ - gl_round_box(GL_POLYGON, strip->start, yminc, strip->end, ymaxc, 9); + gl_round_box_shade(GL_POLYGON, strip->start, yminc, strip->end, ymaxc, 0.0, 0.5, 0.1); /* draw strip outline */ if (strip->flag & NLASTRIP_FLAG_ACTIVE) { @@ -126,16 +125,7 @@ static void nla_draw_strip (NlaTrack *nlt, NlaStrip *strip, int index, View2D *v /* strip should appear to stand out, so draw a dark border around it */ glColor3f(0.0f, 0.0f, 0.0f); } - gl_round_box(GL_LINES, strip->start, yminc, strip->end, ymaxc, 9); - - /* draw some identifying info on the strip (index and name of action if there's room) */ - // XXX for now, just the index - if (strip->flag & NLASTRIP_FLAG_SELECT) - UI_ThemeColor(TH_TEXT_HI); - else - UI_ThemeColor(TH_TEXT); - sprintf(name, "%d |", index); - UI_DrawString(strip->start, yminc+8, name); + gl_round_box_shade(GL_LINE_LOOP, strip->start, yminc, strip->end, ymaxc, 0.0, 0.0, 0.1); } /* ---------------------- */ @@ -147,6 +137,7 @@ void draw_nla_main_data (bAnimContext *ac, SpaceNla *snla, ARegion *ar) int filter; View2D *v2d= &ar->v2d; + float viewWidth = v2d->cur.xmax - v2d->cur.xmin; float y= 0.0f; int items, height; @@ -185,19 +176,33 @@ void draw_nla_main_data (bAnimContext *ac, SpaceNla *snla, ARegion *ar) { NlaTrack *nlt= (NlaTrack *)ale->data; NlaStrip *strip; - int index; /* draw backdrop? */ // TODO... /* draw each strip in the track */ - for (strip=nlt->strips.first, index=1; strip; strip= strip->next, index++) { - /* only draw if at least part of the strip is within view */ - if ( IN_RANGE(v2d->cur.xmin, strip->start, strip->end) || - IN_RANGE(v2d->cur.xmax, strip->start, strip->end) ) + for (strip=nlt->strips.first; strip; strip= strip->next) { + float stripLen= strip->end - strip->start; + + /* only draw if at least part of the strip is within view + * - first 2 cases cover when the strip length is less than the viewable area + * - second 2 cases cover when the strip length is greater than the viewable area + */ + if ( (stripLen < viewWidth) && + !(IN_RANGE(strip->start, v2d->cur.xmin, v2d->cur.xmax) || + IN_RANGE(strip->end, v2d->cur.xmin, v2d->cur.xmax)) ) { - nla_draw_strip(nlt, strip, index, v2d, yminc, ymaxc); + continue; } + if ( (stripLen > viewWidth) && + !(IN_RANGE(v2d->cur.xmin, strip->start, strip->end) || + IN_RANGE(v2d->cur.xmax, strip->start, strip->end)) ) + { + continue; + } + + /* we're still here, so ok... */ + nla_draw_strip(nlt, strip, v2d, yminc, ymaxc); } } break; @@ -521,7 +526,7 @@ void draw_nla_channel_list (bAnimContext *ac, SpaceNla *snla, ARegion *ar) /* object channel - darker */ UI_ThemeColor(TH_DOPESHEET_CHANNELOB); uiSetRoundBox((expand == ICON_TRIA_UP)? (8):(1|8)); - gl_round_box(GL_POLYGON, x+offset, yminc, (float)NLACHANNEL_NAMEWIDTH, ymaxc, 8); + gl_round_box(GL_POLYGON, x+offset, yminc, (float)NLACHANNEL_NAMEWIDTH, ymaxc, 10); } else { /* sub-object folders - lighter */ @@ -547,7 +552,7 @@ void draw_nla_channel_list (bAnimContext *ac, SpaceNla *snla, ARegion *ar) glColor3f(0.6f, 0.5f, 0.5f); // greyish-red color - hardcoded for now offset += 7 * indent; - uiSetRoundBox(15); + uiSetRoundBox((1|2)); // only on top two corners, to show that this channel sits on top of the preceeding ones gl_round_box(GL_POLYGON, x+offset, yminc, (float)NLACHANNEL_NAMEWIDTH, ymaxc, 8); /* clear group value, otherwise we cause errors... */ @@ -610,16 +615,16 @@ void draw_nla_channel_list (bAnimContext *ac, SpaceNla *snla, ARegion *ar) UI_icon_draw((float)(NLACHANNEL_NAMEWIDTH-offset), ydatac, mute); } - /* draw action 'push-down' */ - if (ale->type == ANIMTYPE_NLAACTION) { + /* draw action 'push-down' - only for NLA-Action lines, and only when there's an action */ + if ((ale->type == ANIMTYPE_NLAACTION) && (ale->data)) { offset += 16; /* XXX firstly draw a little rect to help identify that it's different from the toggles */ - glBegin(GL_LINES); - glVertex2f((float)NLACHANNEL_NAMEWIDTH-offset-1, y-7); - glVertex2f((float)NLACHANNEL_NAMEWIDTH-offset-1, y+7); - glVertex2f((float)NLACHANNEL_NAMEWIDTH-1, y-7); - glVertex2f((float)NLACHANNEL_NAMEWIDTH-1, y+7); + glBegin(GL_LINE_LOOP); + glVertex2f((float)NLACHANNEL_NAMEWIDTH-offset-1, y-8); + glVertex2f((float)NLACHANNEL_NAMEWIDTH-offset-1, y+8); + glVertex2f((float)NLACHANNEL_NAMEWIDTH-1, y-8); + glVertex2f((float)NLACHANNEL_NAMEWIDTH-1, y+8); glEnd(); // GL_LINES /* now draw the icon */ From c42eeddea491d6a79dbcc0b8b28386237085643d Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sun, 31 May 2009 04:52:20 +0000 Subject: [PATCH 014/114] NLA SoC: Bugfixes + Improvements to 'Push Down' track-selection * Trying to save no longer crashes in some cases when the NLA Editor was open with some data. The sanity check added in filesel.c might be able to be backported to 2.5? (Elubie, please check) * NLA-track names now get drawn with the correct colours for identifying themselves as being selected or not selected. * Now the 'push down' functionality for actions will try to add the new strip to the last NLA track, provided it has space in the range required. * When new strips are added, they will only be allowed to extrapolate before/after if they are the first (time-wise) strip for the set of NLA data per AnimData block. This stops layered strips overriding strips that occurred in earlier tracks at earlier times. --- source/blender/blenkernel/BKE_nla.h | 3 +- source/blender/blenkernel/intern/nla.c | 156 +++++++++++++----- .../blender/editors/animation/anim_channels.c | 14 ++ source/blender/editors/space_file/filesel.c | 3 + source/blender/editors/space_nla/nla_draw.c | 11 +- 5 files changed, 142 insertions(+), 45 deletions(-) diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index 49796250633..ededd77a92f 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -46,8 +46,9 @@ struct NlaStrip *copy_nlastrip(struct NlaStrip *strip); struct NlaTrack *copy_nlatrack(struct NlaTrack *nlt); void copy_nladata(ListBase *dst, ListBase *src); -struct NlaStrip *add_nlastrip(struct NlaTrack *nlt, struct bAction *act); struct NlaTrack *add_nlatrack(struct AnimData *adt); +struct NlaStrip *add_nlastrip(struct bAction *act); +struct NlaStrip *add_nlastrip_to_stack(struct AnimData *adt, struct bAction *act); /* ----------------------------- */ /* API */ diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 62500af85ff..3efa823f9fe 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -215,19 +215,45 @@ void copy_nladata (ListBase *dst, ListBase *src) /* Adding ------------------------------------------- */ -/* Add a NLA Strip referencing the given Action, to the given NLA Track */ -// TODO: any extra parameters to control how this is done? -NlaStrip *add_nlastrip (NlaTrack *nlt, bAction *act) +/* Add a NLA Track to the given AnimData */ +NlaTrack *add_nlatrack (AnimData *adt) +{ + NlaTrack *nlt; + + /* sanity checks */ + if (adt == NULL) + return NULL; + + /* allocate new track */ + nlt= MEM_callocN(sizeof(NlaTrack), "NlaTrack"); + + /* set settings requiring the track to not be part of the stack yet */ + nlt->flag = NLATRACK_SELECTED; + nlt->index= BLI_countlist(&adt->nla_tracks); + + /* add track to stack, and make it the active one */ + BLI_addtail(&adt->nla_tracks, nlt); + BKE_nlatrack_set_active(&adt->nla_tracks, nlt); + + /* must have unique name, but we need to seed this */ + sprintf(nlt->name, "NlaTrack"); + BLI_uniquename(&adt->nla_tracks, nlt, "NlaTrack", '.', offsetof(NlaTrack, name), 64); + + /* return the new track */ + return nlt; +} + +/* Add a NLA Strip referencing the given Action */ +NlaStrip *add_nlastrip (bAction *act) { NlaStrip *strip; /* sanity checks */ - if ELEM(NULL, nlt, act) + if (act == NULL) return NULL; /* allocate new strip */ strip= MEM_callocN(sizeof(NlaStrip), "NlaStrip"); - BLI_addtail(&nlt->strips, strip); /* generic settings * - selected flag to highlight this to the user @@ -259,32 +285,54 @@ NlaStrip *add_nlastrip (NlaTrack *nlt, bAction *act) return strip; } -/* Add a NLA Track to the given AnimData */ -NlaTrack *add_nlatrack (AnimData *adt) +/* Add new NLA-strip to the top of the NLA stack - i.e. into the last track if space, or a new one otherwise */ +NlaStrip *add_nlastrip_to_stack (AnimData *adt, bAction *act) { + NlaStrip *strip, *ns; NlaTrack *nlt; + short not_added = 1; /* sanity checks */ - if (adt == NULL) + if ELEM(NULL, adt, act) return NULL; - - /* allocate new track */ - nlt= MEM_callocN(sizeof(NlaTrack), "NlaTrack"); - /* set settings requiring the track to not be part of the stack yet */ - nlt->flag = NLATRACK_SELECTED; - nlt->index= BLI_countlist(&adt->nla_tracks); + /* create a new NLA strip */ + strip= add_nlastrip(act); + if (strip == NULL) + return NULL; - /* add track to stack, and make it the active one */ - BLI_addtail(&adt->nla_tracks, nlt); - BKE_nlatrack_set_active(&adt->nla_tracks, nlt); + /* check if the last NLA-track (if it exists) has any space for this strip: + * - if so, add this strip to that track + */ + if ( (adt->nla_tracks.last == NULL) || + (BKE_nlatrack_has_space(adt->nla_tracks.last, strip->start, strip->end)==0) ) + { + /* no space, so add to a new track... */ + nlt= add_nlatrack(adt); + } + else + { + /* there's some space, so add to this track... */ + nlt= adt->nla_tracks.last; + } - /* must have unique name, but we need to seed this */ - sprintf(nlt->name, "NlaTrack"); - BLI_uniquename(&adt->nla_tracks, nlt, "NlaTrack", '.', offsetof(NlaTrack, name), 64); + /* find the right place to add the strip to the nominated track */ + for (ns= nlt->strips.first; ns; ns= ns->next) { + /* if current strip occurs after the new strip, add it before */ + if (ns->start > strip->end) { + BLI_insertlinkbefore(&nlt->strips, ns, strip); + not_added= 0; + break; + } + } + if (not_added) { + /* just add to the end of the list of the strips then... */ + BLI_addtail(&nlt->strips, strip); + } - /* return the new track */ - return nlt; + + /* returns the strip added */ + return strip; } /* *************************************************** */ @@ -404,7 +452,39 @@ void BKE_nlatrack_sort_strips (NlaTrack *nlt) nlt->strips.first= tmp.first; nlt->strips.last= tmp.last; } - + +/* NLA Strips -------------------------------------- */ + +/* 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) +{ + NlaTrack *nlt; + NlaStrip *ns; + + /* sanity checks */ + if ELEM(NULL, adt, strip) + return 0; + + /* check if strip has any strips before it */ + if (strip->prev) + return 0; + + /* check other tracks to see if they have a strip that's earlier */ + // TODO: or should we check that the strip's track is also the first? + for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) { + /* only check the first strip, assuming that they're all in order */ + ns= nlt->strips.first; + if (ns) { + if (ns->start < strip->start) + return 0; + } + } + + /* should be first now */ + return 1; +} + /* Tools ------------------------------------------- */ /* For the given AnimData block, add the active action to the NLA @@ -415,7 +495,6 @@ void BKE_nlatrack_sort_strips (NlaTrack *nlt) // TODO: maybe we should have checks for this too... void BKE_nla_action_pushdown (AnimData *adt) { - NlaTrack *nlt; NlaStrip *strip; /* sanity checks */ @@ -431,28 +510,27 @@ void BKE_nla_action_pushdown (AnimData *adt) printf("BKE_nla_action_pushdown(): action has no data \n"); return; } - - /* add a new NLA track to house this action - * - we could investigate trying to fit the action into an appropriately - * sized gap in the existing tracks, however, this may result in unexpected - * changes in blending behaviour... - */ - nlt= add_nlatrack(adt); - if (nlt == NULL) { - printf("BKE_nla_action_pushdown(): no NLA-track added \n"); - return; - } /* add a new NLA strip to the track, which references the active action */ - strip= add_nlastrip(nlt, adt->action); + strip= add_nlastrip_to_stack(adt, adt->action); - /* clear reference to action now that we've pushed it onto the stack */ + /* do other necessary work on strip */ if (strip) { + /* clear reference to action now that we've pushed it onto the stack */ adt->action->id.us--; adt->action= NULL; + + /* if the strip is the first one in the track it lives in, check if there + * are strips in any other tracks that may be before this, and set the extend + * mode accordingly + */ + if (nlastrip_is_first(adt, strip) == 0) { + /* not first, so extend mode can only be NLASTRIP_EXTEND_HOLD_FORWARD not NLASTRIP_EXTEND_HOLD, + * so that it doesn't override strips in previous tracks + */ + strip->extendmode= NLASTRIP_EXTEND_HOLD_FORWARD; + } } - - // TODO: set any other flags necessary here... } /* *************************************************** */ diff --git a/source/blender/editors/animation/anim_channels.c b/source/blender/editors/animation/anim_channels.c index a5f2acb591c..5d5be87801b 100644 --- a/source/blender/editors/animation/anim_channels.c +++ b/source/blender/editors/animation/anim_channels.c @@ -149,6 +149,13 @@ void ANIM_set_active_channel (void *data, short datatype, int filter, void *chan ACHANNEL_SET_FLAG(fcu, ACHANNEL_SETFLAG_CLEAR, FCURVE_ACTIVE); } break; + case ANIMTYPE_NLATRACK: + { + NlaTrack *nlt= (NlaTrack *)ale->data; + + ACHANNEL_SET_FLAG(nlt, ACHANNEL_SETFLAG_CLEAR, NLATRACK_ACTIVE); + } + break; } } @@ -167,6 +174,13 @@ void ANIM_set_active_channel (void *data, short datatype, int filter, void *chan fcu->flag |= FCURVE_ACTIVE; } break; + case ANIMTYPE_NLATRACK: + { + NlaTrack *nlt= (NlaTrack *)channel_data; + + ACHANNEL_SET_FLAG(nlt, ACHANNEL_SETFLAG_CLEAR, NLATRACK_ACTIVE); + } + break; } } diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c index cbd1457e562..091319cd402 100644 --- a/source/blender/editors/space_file/filesel.c +++ b/source/blender/editors/space_file/filesel.c @@ -144,6 +144,9 @@ int ED_fileselect_layout_offset(FileLayout* layout, int x, int y) int offsetx, offsety; int active_file; + if (layout == NULL) + return NULL; + offsetx = (x)/(layout->tile_w + 2*layout->tile_border_x); offsety = (y)/(layout->tile_h + 2*layout->tile_border_y); diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index 28572704302..1a289d8436b 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -296,7 +296,7 @@ void draw_nla_channel_list (bAnimContext *ac, SpaceNla *snla, ARegion *ar) indent= 0; special= ICON_SCENE_DATA; - + /* only show expand if there are any channels */ if (EXPANDED_SCEC(sce)) expand= ICON_TRIA_UP; @@ -484,6 +484,7 @@ void draw_nla_channel_list (bAnimContext *ac, SpaceNla *snla, ARegion *ar) else protect = ICON_LOCKED; + sel = SEL_NLT(nlt); strcpy(name, nlt->name); } break; @@ -621,10 +622,10 @@ void draw_nla_channel_list (bAnimContext *ac, SpaceNla *snla, ARegion *ar) /* XXX firstly draw a little rect to help identify that it's different from the toggles */ glBegin(GL_LINE_LOOP); - glVertex2f((float)NLACHANNEL_NAMEWIDTH-offset-1, y-8); - glVertex2f((float)NLACHANNEL_NAMEWIDTH-offset-1, y+8); - glVertex2f((float)NLACHANNEL_NAMEWIDTH-1, y-8); - glVertex2f((float)NLACHANNEL_NAMEWIDTH-1, y+8); + glVertex2f((float)NLACHANNEL_NAMEWIDTH-offset-1, y-7); + glVertex2f((float)NLACHANNEL_NAMEWIDTH-offset-1, y+9); + glVertex2f((float)NLACHANNEL_NAMEWIDTH-1, y+9); + glVertex2f((float)NLACHANNEL_NAMEWIDTH-1, y-7); glEnd(); // GL_LINES /* now draw the icon */ From 33267f58581ea8f9d89028958c6e64a8d048d4db Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sun, 31 May 2009 11:14:50 +0000 Subject: [PATCH 015/114] NLA SoC: Basic selection operators * Added click-select/left-right select and deselect all/invert all selection operators. For now, these basic operators will suffice (more advanced selection operators will be coded at a later stage). * Fixed a few bugs in DopeSheet found while coding the relevant tools for NLA. * Added custom border-select operator for NLA channels (since the standard one assumes negative direction channel order) * Added new API-method for NLA strips to check if the strip occurs within a given range, since this test needed to be performed in a few places... * Tweaked the NLA Editor View2D ranges a bit to give saner default sizing. This still isn't right yet though. --- source/blender/blenkernel/BKE_nla.h | 2 + source/blender/blenkernel/intern/nla.c | 31 ++ .../blender/editors/animation/anim_channels.c | 26 -- source/blender/editors/include/ED_anim_api.h | 27 +- .../editors/space_action/action_select.c | 3 +- .../blender/editors/space_nla/nla_channels.c | 110 ++++- source/blender/editors/space_nla/nla_draw.c | 26 +- source/blender/editors/space_nla/nla_intern.h | 17 +- source/blender/editors/space_nla/nla_ops.c | 23 +- source/blender/editors/space_nla/nla_select.c | 440 ++++++++++++++++++ source/blender/editors/space_nla/space_nla.c | 4 +- 11 files changed, 648 insertions(+), 61 deletions(-) create mode 100644 source/blender/editors/space_nla/nla_select.c diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index ededd77a92f..3c3abe11da3 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -59,6 +59,8 @@ void BKE_nlatrack_set_active(ListBase *tracks, struct NlaTrack *nlt); short BKE_nlatrack_has_space(struct NlaTrack *nlt, float start, float end); void BKE_nlatrack_sort_strips(struct NlaTrack *nlt); +short BKE_nlastrip_within_bounds(struct NlaStrip *strip, float min, float max); + void BKE_nla_action_pushdown(struct AnimData *adt); #endif diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 3efa823f9fe..cf115cb6faf 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -455,6 +455,37 @@ void BKE_nlatrack_sort_strips (NlaTrack *nlt) /* NLA Strips -------------------------------------- */ +/* Does the given NLA-strip fall within the given bounds (times)? */ +short BKE_nlastrip_within_bounds (NlaStrip *strip, float min, float max) +{ + const float stripLen= (strip) ? strip->end - strip->start : 0.0f; + const float boundsLen= (float)fabs(max - min); + + /* sanity checks */ + if ((strip == NULL) || IS_EQ(stripLen, 0.0f) || IS_EQ(boundsLen, 0.0f)) + return 0; + + /* only ok if at least part of the strip is within the bounding window + * - first 2 cases cover when the strip length is less than the bounding area + * - second 2 cases cover when the strip length is greater than the bounding area + */ + if ( (stripLen < boundsLen) && + !(IN_RANGE(strip->start, min, max) || + IN_RANGE(strip->end, min, max)) ) + { + return 0; + } + if ( (stripLen > boundsLen) && + !(IN_RANGE(min, strip->start, strip->end) || + IN_RANGE(max, strip->start, strip->end)) ) + { + return 0; + } + + /* should be ok! */ + return 1; +} + /* 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) diff --git a/source/blender/editors/animation/anim_channels.c b/source/blender/editors/animation/anim_channels.c index 5d5be87801b..658bff73978 100644 --- a/source/blender/editors/animation/anim_channels.c +++ b/source/blender/editors/animation/anim_channels.c @@ -87,32 +87,6 @@ /* ************************************************************************** */ /* CHANNELS API */ -/* -------------------------- Internal Macros ------------------------------- */ - -/* set/clear/toggle macro - * - channel - channel with a 'flag' member that we're setting - * - smode - 0=clear, 1=set, 2=toggle - * - sflag - bitflag to set - */ -#define ACHANNEL_SET_FLAG(channel, smode, sflag) \ - { \ - if (smode == ACHANNEL_SETFLAG_TOGGLE) (channel)->flag ^= (sflag); \ - else if (smode == ACHANNEL_SETFLAG_ADD) (channel)->flag |= (sflag); \ - else (channel)->flag &= ~(sflag); \ - } - -/* set/clear/toggle macro, where the flag is negative - * - channel - channel with a 'flag' member that we're setting - * - smode - 0=clear, 1=set, 2=toggle - * - sflag - bitflag to set - */ -#define ACHANNEL_SET_FLAG_NEG(channel, smode, sflag) \ - { \ - if (smode == ACHANNEL_SETFLAG_TOGGLE) (channel)->flag ^= (sflag); \ - else if (smode == ACHANNEL_SETFLAG_ADD) (channel)->flag &= ~(sflag); \ - else (channel)->flag |= (sflag); \ - } - /* -------------------------- Exposed API ----------------------------------- */ /* Set the given animation-channel as the active one for the active context */ diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index 7629fc29352..cdd8b5c368c 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -317,10 +317,35 @@ void ANIM_nla_mapping_draw(struct gla2DDrawInfo *di, struct Object *ob, short re /* Apply/Unapply NLA mapping to all keyframes in the nominated IPO block */ void ANIM_nla_mapping_apply_fcurve(struct Object *ob, struct FCurve *fcu, short restore, short only_keys); -/* ------------- xxx macros ----------------------- */ +/* ------------- Utility macros ----------------------- */ +/* checks if the given BezTriple is selected */ #define BEZSELECTED(bezt) ((bezt->f2 & SELECT) || (bezt->f1 & SELECT) || (bezt->f3 & SELECT)) +/* set/clear/toggle macro + * - channel - channel with a 'flag' member that we're setting + * - smode - 0=clear, 1=set, 2=toggle + * - sflag - bitflag to set + */ +#define ACHANNEL_SET_FLAG(channel, smode, sflag) \ + { \ + if (smode == ACHANNEL_SETFLAG_TOGGLE) (channel)->flag ^= (sflag); \ + else if (smode == ACHANNEL_SETFLAG_ADD) (channel)->flag |= (sflag); \ + else (channel)->flag &= ~(sflag); \ + } + +/* set/clear/toggle macro, where the flag is negative + * - channel - channel with a 'flag' member that we're setting + * - smode - 0=clear, 1=set, 2=toggle + * - sflag - bitflag to set + */ +#define ACHANNEL_SET_FLAG_NEG(channel, smode, sflag) \ + { \ + if (smode == ACHANNEL_SETFLAG_TOGGLE) (channel)->flag ^= (sflag); \ + else if (smode == ACHANNEL_SETFLAG_ADD) (channel)->flag &= ~(sflag); \ + else (channel)->flag |= (sflag); \ + } + /* --------- anim_deps.c, animation updates -------- */ diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c index d4782418be7..f64cd0f707c 100644 --- a/source/blender/editors/space_action/action_select.c +++ b/source/blender/editors/space_action/action_select.c @@ -174,7 +174,7 @@ static int actkeys_deselectall_exec(bContext *C, wmOperator *op) deselect_action_keys(&ac, 1, SELECT_ADD); /* set notifier that things have changed */ - ED_area_tag_redraw(CTX_wm_area(C)); // FIXME... should be updating 'keyframes' data context or so instead! + ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); return OPERATOR_FINISHED; } @@ -766,6 +766,7 @@ static void mouse_action_keys (bAnimContext *ac, int mval[2], short select_mode, if (ale == NULL) { /* channel not found */ printf("Error: animation channel (index = %d) not found in mouse_action_keys() \n", channel_index); + BLI_freelistN(&anim_data); return; } else { diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c index 658ce69cc10..a839ccbf3d6 100644 --- a/source/blender/editors/space_nla/nla_channels.c +++ b/source/blender/editors/space_nla/nla_channels.c @@ -82,7 +82,115 @@ /* *********************************************** */ /* Operators for NLA channels-list which need to be different from the standard Animation Editor ones */ -// TODO: implemented borderselect too, since that also relies on ranges of buttons +/* ******************** Borderselect Operator *********************** */ + +static void borderselect_nla_channels (bAnimContext *ac, rcti *rect, short selectmode) +{ + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + View2D *v2d= &ac->ar->v2d; + rctf rectf; + float ymin=(float)(-NLACHANNEL_HEIGHT), ymax=0; + + /* convert border-region to view coordinates */ + UI_view2d_region_to_view(v2d, rect->xmin, rect->ymin+2, &rectf.xmin, &rectf.ymin); + UI_view2d_region_to_view(v2d, rect->xmax, rect->ymax-2, &rectf.xmax, &rectf.ymax); + + /* filter data */ + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CHANNELS); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + /* loop over data, doing border select */ + for (ale= anim_data.first; ale; ale= ale->next) { + ymax= ymin + NLACHANNEL_STEP; + + /* if channel is within border-select region, alter it */ + if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))) { + /* only the following types can be selected */ + switch (ale->type) { + case ANIMTYPE_OBJECT: /* object */ + { + Base *base= (Base *)ale->data; + Object *ob= base->object; + + ACHANNEL_SET_FLAG(base, selectmode, SELECT); + ACHANNEL_SET_FLAG(ob, selectmode, SELECT); + } + break; + case ANIMTYPE_NLATRACK: /* nla-track */ + { + NlaTrack *nlt= (NlaTrack *)ale->data; + + ACHANNEL_SET_FLAG(nlt, selectmode, NLATRACK_SELECTED); + } + break; + } + } + + /* set maximum extent to be the minimum of the next channel */ + ymin= ymax; + } + + /* cleanup */ + BLI_freelistN(&anim_data); +} + +/* ------------------- */ + +static int nlachannels_borderselect_exec(bContext *C, wmOperator *op) +{ + bAnimContext ac; + rcti rect; + short selectmode=0; + int event; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* get settings from operator */ + rect.xmin= RNA_int_get(op->ptr, "xmin"); + rect.ymin= RNA_int_get(op->ptr, "ymin"); + rect.xmax= RNA_int_get(op->ptr, "xmax"); + rect.ymax= RNA_int_get(op->ptr, "ymax"); + + event= RNA_int_get(op->ptr, "event_type"); + if (event == LEFTMOUSE) // FIXME... hardcoded + selectmode = ACHANNEL_SETFLAG_ADD; + else + selectmode = ACHANNEL_SETFLAG_CLEAR; + + /* apply borderselect animation channels */ + borderselect_nla_channels(&ac, &rect, selectmode); + + return OPERATOR_FINISHED; +} + +void NLA_OT_channels_select_border(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Border Select"; + ot->idname= "NLA_OT_channels_select_border"; + + /* api callbacks */ + ot->invoke= WM_border_select_invoke; + ot->exec= nlachannels_borderselect_exec; + ot->modal= WM_border_select_modal; + + ot->poll= ED_operator_areaactive; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* rna */ + RNA_def_int(ot->srna, "event_type", 0, INT_MIN, INT_MAX, "Event Type", "", INT_MIN, INT_MAX); + RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX); + 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); +} /* ******************** Mouse-Click Operator *********************** */ /* Depending on the channel that was clicked on, the mouse click will activate whichever diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index 1a289d8436b..def49021160 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -137,7 +137,6 @@ void draw_nla_main_data (bAnimContext *ac, SpaceNla *snla, ARegion *ar) int filter; View2D *v2d= &ar->v2d; - float viewWidth = v2d->cur.xmax - v2d->cur.xmin; float y= 0.0f; int items, height; @@ -180,29 +179,10 @@ void draw_nla_main_data (bAnimContext *ac, SpaceNla *snla, ARegion *ar) /* draw backdrop? */ // TODO... - /* draw each strip in the track */ + /* draw each strip in the track (if visible) */ for (strip=nlt->strips.first; strip; strip= strip->next) { - float stripLen= strip->end - strip->start; - - /* only draw if at least part of the strip is within view - * - first 2 cases cover when the strip length is less than the viewable area - * - second 2 cases cover when the strip length is greater than the viewable area - */ - if ( (stripLen < viewWidth) && - !(IN_RANGE(strip->start, v2d->cur.xmin, v2d->cur.xmax) || - IN_RANGE(strip->end, v2d->cur.xmin, v2d->cur.xmax)) ) - { - continue; - } - if ( (stripLen > viewWidth) && - !(IN_RANGE(v2d->cur.xmin, strip->start, strip->end) || - IN_RANGE(v2d->cur.xmax, strip->start, strip->end)) ) - { - continue; - } - - /* we're still here, so ok... */ - nla_draw_strip(nlt, strip, v2d, yminc, ymaxc); + if (BKE_nlastrip_within_bounds(strip, v2d->cur.xmin, v2d->cur.xmax)) + nla_draw_strip(nlt, strip, v2d, yminc, ymaxc); } } break; diff --git a/source/blender/editors/space_nla/nla_intern.h b/source/blender/editors/space_nla/nla_intern.h index 37eb7774696..448b823bd4b 100644 --- a/source/blender/editors/space_nla/nla_intern.h +++ b/source/blender/editors/space_nla/nla_intern.h @@ -17,11 +17,11 @@ * 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) 2008 Blender Foundation. + * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung. * All rights reserved. * * - * Contributor(s): Blender Foundation + * Contributor(s): Blender Foundation, Joshua Leung * * ***** END GPL LICENSE BLOCK ***** */ @@ -60,6 +60,18 @@ void nla_header_buttons(const bContext *C, ARegion *ar); /* **************************************** */ /* nla_select.c */ +/* defines for left-right select tool */ +enum { + NLAEDIT_LRSEL_TEST = -1, + NLAEDIT_LRSEL_NONE, + NLAEDIT_LRSEL_LEFT, + NLAEDIT_LRSEL_RIGHT, +} eNlaEdit_LeftRightSelect_Mode; + +/* --- */ + +void NLAEDIT_OT_select_all_toggle(wmOperatorType *ot); +void NLAEDIT_OT_click_select(wmOperatorType *ot); /* **************************************** */ /* nla_edit.c */ @@ -67,6 +79,7 @@ void nla_header_buttons(const bContext *C, ARegion *ar); /* **************************************** */ /* nla_channels.c */ +void NLA_OT_channels_select_border(wmOperatorType *ot); void NLA_OT_channels_click(wmOperatorType *ot); /* **************************************** */ diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c index ea450a08475..167686c99f9 100644 --- a/source/blender/editors/space_nla/nla_ops.c +++ b/source/blender/editors/space_nla/nla_ops.c @@ -72,9 +72,11 @@ void nla_operatortypes(void) { /* channels */ WM_operatortype_append(NLA_OT_channels_click); + WM_operatortype_append(NLA_OT_channels_select_border); /* select */ - // ... + WM_operatortype_append(NLAEDIT_OT_click_select); + WM_operatortype_append(NLAEDIT_OT_select_all_toggle); } /* ************************** registration - keymaps **********************************/ @@ -88,14 +90,14 @@ static void nla_keymap_channels (wmWindowManager *wm, ListBase *keymap) WM_keymap_add_item(keymap, "NLA_OT_channels_click", LEFTMOUSE, KM_PRESS, 0, 0); RNA_boolean_set(WM_keymap_add_item(keymap, "NLA_OT_channels_click", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "extend", 1); + /* borderselect */ + WM_keymap_add_item(keymap, "NLA_OT_channels_select_border", BKEY, KM_PRESS, 0, 0); + /* General Animation Channels keymap (see anim_channels.c) ----------------------- */ /* deselect all */ WM_keymap_add_item(keymap, "ANIM_OT_channels_select_all_toggle", AKEY, KM_PRESS, 0, 0); RNA_boolean_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_select_all_toggle", IKEY, KM_PRESS, KM_CTRL, 0)->ptr, "invert", 1); - /* borderselect */ - WM_keymap_add_item(keymap, "ANIM_OT_channels_select_border", BKEY, KM_PRESS, 0, 0); - /* settings */ WM_keymap_add_item(keymap, "ANIM_OT_channels_setting_toggle", WKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "ANIM_OT_channels_setting_enable", WKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0); @@ -114,8 +116,19 @@ static void nla_keymap_channels (wmWindowManager *wm, ListBase *keymap) static void nla_keymap_main (wmWindowManager *wm, ListBase *keymap) { - //wmKeymapItem *kmi; + wmKeymapItem *kmi; + /* selection */ + /* click select */ + WM_keymap_add_item(keymap, "NLAEDIT_OT_click_select", SELECTMOUSE, KM_PRESS, 0, 0); + kmi= WM_keymap_add_item(keymap, "NLAEDIT_OT_click_select", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0); + RNA_boolean_set(kmi->ptr, "extend", 1); + kmi= WM_keymap_add_item(keymap, "NLAEDIT_OT_click_select", SELECTMOUSE, KM_PRESS, KM_CTRL, 0); + RNA_enum_set(kmi->ptr, "left_right", NLAEDIT_LRSEL_TEST); + + /* deselect all */ + WM_keymap_add_item(keymap, "NLAEDIT_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0); + RNA_boolean_set(WM_keymap_add_item(keymap, "NLAEDIT_OT_select_all_toggle", IKEY, KM_PRESS, KM_CTRL, 0)->ptr, "invert", 1); /* transform system */ diff --git a/source/blender/editors/space_nla/nla_select.c b/source/blender/editors/space_nla/nla_select.c new file mode 100644 index 00000000000..5d9fe5f2a05 --- /dev/null +++ b/source/blender/editors/space_nla/nla_select.c @@ -0,0 +1,440 @@ +/** + * $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 + * All rights reserved. + * + * + * Contributor(s): Joshua Leung (major recode) + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include +#include + +#include "DNA_anim_types.h" +#include "DNA_action_types.h" +#include "DNA_nla_types.h" +#include "DNA_object_types.h" +#include "DNA_space_types.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" +#include "DNA_windowmanager_types.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" +#include "BLI_arithb.h" +#include "BLI_rand.h" + +#include "BKE_animsys.h" +#include "BKE_nla.h" +#include "BKE_context.h" +#include "BKE_report.h" +#include "BKE_screen.h" + +#include "ED_anim_api.h" +#include "ED_keyframes_edit.h" +#include "ED_markers.h" +#include "ED_space_api.h" +#include "ED_screen.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "UI_interface.h" +#include "UI_resources.h" +#include "UI_view2d.h" + +#include "nla_intern.h" // own include + +/* ******************** Utilities ***************************************** */ + +/* Convert SELECT_* flags to ACHANNEL_SETFLAG_* flags */ +static short selmodes_to_flagmodes (short sel) +{ + /* convert selection modes to selection modes */ + switch (sel) { + case SELECT_SUBTRACT: + return ACHANNEL_SETFLAG_CLEAR; + break; + + case SELECT_INVERT: + return ACHANNEL_SETFLAG_TOGGLE; + break; + + case SELECT_ADD: + default: + return ACHANNEL_SETFLAG_ADD; + break; + } +} + + +/* ******************** Deselect All Operator ***************************** */ +/* This operator works in one of three ways: + * 1) (de)select all (AKEY) - test if select all or deselect all + * 2) invert all (CTRL-IKEY) - invert selection of all keyframes + * 3) (de)select all - no testing is done; only for use internal tools as normal function... + */ + +/* Deselects strips in the NLA Editor + * - This is called by the deselect all operator, as well as other ones! + * + * - test: check if select or deselect all + * - sel: how to select keyframes + * 0 = deselect + * 1 = select + * 2 = invert + */ +static void deselect_nla_strips (bAnimContext *ac, short test, short sel) +{ + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + short smode; + + /* determine type-based settings - curvesonly eliminates all the unnecessary channels... */ + filter= (ANIMFILTER_VISIBLE|ANIMFILTER_CURVESONLY); + + /* filter data */ + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + /* See if we should be selecting or deselecting */ + if (test) { + for (ale= anim_data.first; ale; ale= ale->next) { + NlaTrack *nlt= (NlaTrack *)ale->data; + NlaStrip *strip; + + /* if any strip is selected, break out, since we should now be deselecting */ + for (strip= nlt->strips.first; strip; strip= strip->next) { + if (strip->flag & NLASTRIP_FLAG_SELECT) { + sel= SELECT_SUBTRACT; + break; + } + } + + if (sel == SELECT_SUBTRACT) + break; + } + } + + /* convert selection modes to selection modes */ + smode= selmodes_to_flagmodes(sel); + + /* Now set the flags */ + for (ale= anim_data.first; ale; ale= ale->next) { + NlaTrack *nlt= (NlaTrack *)ale->data; + NlaStrip *strip; + + /* apply same selection to all strips */ + for (strip= nlt->strips.first; strip; strip= strip->next) { + /* set selection */ + ACHANNEL_SET_FLAG(strip, smode, NLASTRIP_FLAG_SELECT); + + /* clear active flag */ + strip->flag &= ~NLASTRIP_FLAG_ACTIVE; + } + } + + /* Cleanup */ + BLI_freelistN(&anim_data); +} + +/* ------------------- */ + +static int nlaedit_deselectall_exec(bContext *C, wmOperator *op) +{ + bAnimContext ac; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* 'standard' behaviour - check if selected, then apply relevant selection */ + if (RNA_boolean_get(op->ptr, "invert")) + deselect_nla_strips(&ac, 0, SELECT_INVERT); + else + deselect_nla_strips(&ac, 1, SELECT_ADD); + + /* set notifier that things have changed */ + ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); + + return OPERATOR_FINISHED; +} + +void NLAEDIT_OT_select_all_toggle (wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Select All"; + ot->idname= "NLAEDIT_OT_select_all_toggle"; + + /* api callbacks */ + ot->exec= nlaedit_deselectall_exec; + ot->poll= ED_operator_areaactive; + + /* flags */ + ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/; + + /* props */ + RNA_def_boolean(ot->srna, "invert", 0, "Invert", ""); +} + +/* ******************** Mouse-Click Select Operator *********************** */ +/* This operator works in one of 2 ways: + * 1) Select the strip directly under the mouse + * 2) Select all the strips to one side of the mouse + */ + +/* defines for left-right select tool */ +static EnumPropertyItem prop_nlaedit_leftright_select_types[] = { + {NLAEDIT_LRSEL_TEST, "CHECK", "Check if Select Left or Right", ""}, + {NLAEDIT_LRSEL_NONE, "OFF", "Don't select", ""}, + {NLAEDIT_LRSEL_LEFT, "LEFT", "Before current frame", ""}, + {NLAEDIT_LRSEL_RIGHT, "RIGHT", "After current frame", ""}, + {0, NULL, NULL, NULL} +}; + +/* sensitivity factor for frame-selections */ +#define FRAME_CLICK_THRESH 0.1f + + +/* ------------------- */ + +/* option 1) select strip directly under mouse */ +static void mouse_nla_strips (bAnimContext *ac, int mval[2], short select_mode) +{ + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale = NULL; + int filter; + + View2D *v2d= &ac->ar->v2d; + NlaStrip *strip = NULL; + int channel_index; + float xmin, xmax, dummy; + float x, y; + + + /* use View2D to determine the index of the channel (i.e a row in the list) where keyframe was */ + UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y); + UI_view2d_listview_view_to_cell(v2d, 0, NLACHANNEL_STEP, 0, 0, x, y, NULL, &channel_index); + + /* x-range to check is +/- 7 (in screen/region-space) on either side of mouse click + * (that is the size of keyframe icons, so user should be expecting similar tolerances) + */ + UI_view2d_region_to_view(v2d, mval[0]-7, mval[1], &xmin, &dummy); + UI_view2d_region_to_view(v2d, mval[0]+7, mval[1], &xmax, &dummy); + + /* filter data */ + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CHANNELS); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + /* try to get channel */ + ale= BLI_findlink(&anim_data, channel_index); + if (ale == NULL) { + /* channel not found */ + printf("Error: animation channel (index = %d) not found in mouse_nla_strips() \n", channel_index); + BLI_freelistN(&anim_data); + return; + } + else { + /* found some channel - we only really should do somethign when its an Nla-Track */ + if (ale->type == ANIMTYPE_NLATRACK) { + NlaTrack *nlt= (NlaTrack *)ale->data; + + /* loop over NLA-strips in this track, trying to find one which occurs in the necessary bounds */ + for (strip= nlt->strips.first; strip; strip= strip->next) { + if (BKE_nlastrip_within_bounds(strip, xmin, xmax)) + break; + } + } + + /* remove active channel from list of channels for separate treatment (since it's needed later on) */ + BLI_remlink(&anim_data, ale); + + /* free list of channels, since it's not used anymore */ + BLI_freelistN(&anim_data); + } + + /* for replacing selection, firstly need to clear existing selection */ + if (select_mode == SELECT_REPLACE) { + /* reset selection mode for next steps */ + select_mode = SELECT_ADD; + + /* deselect all strips */ + deselect_nla_strips(ac, 0, SELECT_SUBTRACT); + + /* deselect all other channels first */ + ANIM_deselect_anim_channels(ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR); + + /* Highlight NLA-Track */ + if (ale->type == ANIMTYPE_NLATRACK) { + NlaTrack *nlt= (NlaTrack *)ale->data; + + nlt->flag |= NLATRACK_SELECTED; + ANIM_set_active_channel(ac->data, ac->datatype, filter, nlt, ANIMTYPE_NLATRACK); + } + } + + /* only select strip if we clicked on a valid channel and hit something */ + if (ale) { + /* select the strip accordingly (if a matching one was found) */ + if (strip) { + select_mode= selmodes_to_flagmodes(select_mode); + ACHANNEL_SET_FLAG(strip, select_mode, NLASTRIP_FLAG_SELECT); + } + + /* free this channel */ + MEM_freeN(ale); + } +} + +/* Option 2) Selects all the strips on either side of the current frame (depends on which side the mouse is on) */ +static void nlaedit_mselect_leftright (bAnimContext *ac, short leftright, short select_mode) +{ + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + Scene *scene= ac->scene; + float xmin, xmax; + + /* if select mode is replace, deselect all keyframes (and channels) first */ + if (select_mode==SELECT_REPLACE) { + select_mode= SELECT_ADD; + + /* deselect all other channels and keyframes */ + ANIM_deselect_anim_channels(ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR); + deselect_nla_strips(ac, 0, SELECT_SUBTRACT); + } + + /* get range, and get the right flag-setting mode */ + if (leftright == NLAEDIT_LRSEL_LEFT) { + xmin = -MAXFRAMEF; + xmax = (float)(CFRA + FRAME_CLICK_THRESH); + } + else { + xmin = (float)(CFRA - FRAME_CLICK_THRESH); + xmax = MAXFRAMEF; + } + + select_mode= selmodes_to_flagmodes(select_mode); + + + /* filter data */ + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVESONLY); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + /* select strips on the side where most data occurs */ + for (ale= anim_data.first; ale; ale= ale->next) { + NlaTrack *nlt= (NlaTrack *)ale->data; + NlaStrip *strip; + + /* check each strip to see if it is appropriate */ + for (strip= nlt->strips.first; strip; strip= strip->next) { + if (BKE_nlastrip_within_bounds(strip, xmin, xmax)) { + ACHANNEL_SET_FLAG(strip, select_mode, NLASTRIP_FLAG_SELECT); + } + } + } + + /* Cleanup */ + BLI_freelistN(&anim_data); +} + +/* ------------------- */ + +/* handle clicking */ +static int nlaedit_clickselect_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + bAnimContext ac; + Scene *scene; + ARegion *ar; + View2D *v2d; + short selectmode; + int mval[2]; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* get useful pointers from animation context data */ + scene= ac.scene; + ar= ac.ar; + v2d= &ar->v2d; + + /* get mouse coordinates (in region coordinates) */ + mval[0]= (event->x - ar->winrct.xmin); + mval[1]= (event->y - ar->winrct.ymin); + + /* select mode is either replace (deselect all, then add) or add/extend */ + if (RNA_boolean_get(op->ptr, "extend")) + selectmode= SELECT_INVERT; + else + selectmode= SELECT_REPLACE; + + /* figure out action to take */ + if (RNA_enum_get(op->ptr, "left_right")) { + /* select all keys on same side of current frame as mouse */ + float x; + + UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, NULL); + if (x < CFRA) + RNA_int_set(op->ptr, "left_right", NLAEDIT_LRSEL_LEFT); + else + RNA_int_set(op->ptr, "left_right", NLAEDIT_LRSEL_RIGHT); + + nlaedit_mselect_leftright(&ac, RNA_enum_get(op->ptr, "left_right"), selectmode); + } + else { + /* select strips based upon mouse position */ + mouse_nla_strips(&ac, mval, selectmode); + } + + /* set notifier that things have changed */ + ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); + + /* for tweak grab to work */ + return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH; +} + +void NLAEDIT_OT_click_select (wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Mouse Select"; + ot->idname= "NLAEDIT_OT_click_select"; + + /* api callbacks - absolutely no exec() this yet... */ + ot->invoke= nlaedit_clickselect_invoke; + ot->poll= ED_operator_areaactive; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* id-props */ + // XXX should we make this into separate operators? + RNA_def_enum(ot->srna, "left_right", prop_nlaedit_leftright_select_types, 0, "Left Right", ""); // CTRLKEY + RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); // SHIFTKEY +} + +/* *********************************************** */ diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c index 1313b4d915d..024b23c51b8 100644 --- a/source/blender/editors/space_nla/space_nla.c +++ b/source/blender/editors/space_nla/space_nla.c @@ -105,12 +105,12 @@ static SpaceLink *nla_new(const bContext *C) ar->v2d.tot.xmin= 1.0f; ar->v2d.tot.ymin= 0.0f; ar->v2d.tot.xmax= 1000.0f; - ar->v2d.tot.ymax= 1000.0f; + ar->v2d.tot.ymax= 500.0f; ar->v2d.cur.xmin= -5.0f; ar->v2d.cur.ymin= 0.0f; ar->v2d.cur.xmax= 65.0f; - ar->v2d.cur.ymax= 1000.0f; + ar->v2d.cur.ymax= 250.0f; ar->v2d.min[0]= 0.0f; ar->v2d.min[1]= 0.0f; From 6a35302a54071bfd12df7d4a71e710d1e250b34d Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 2 Jun 2009 09:58:06 +0000 Subject: [PATCH 016/114] NLA SoC: Fixed merge errors. Manually copied over any files from 2.5 that were modified in a commit by Brecht between the time when I had done the previous merge and the time when the commit for that finally got through. --- source/blender/blenkernel/BKE_library.h | 1 + source/blender/blenkernel/intern/library.c | 6 + source/blender/editors/include/ED_object.h | 17 +- source/blender/editors/include/UI_interface.h | 9 +- source/blender/editors/interface/interface.c | 13 +- .../blender/editors/interface/interface_api.c | 11 +- .../editors/interface/interface_handlers.c | 6 +- .../editors/interface/interface_utils.c | 4 +- .../editors/interface/interface_widgets.c | 6 +- .../blender/editors/object/editconstraint.c | 293 +++++++++++++++--- source/blender/editors/object/object_intern.h | 3 + .../blender/editors/object/object_modifier.c | 2 + source/blender/editors/object/object_ops.c | 2 + .../editors/space_image/image_header.c | 14 +- .../editors/space_view3d/view3d_header.c | 24 +- source/blender/makesrna/RNA_enum_types.h | 1 + .../blender/makesrna/intern/rna_constraint.c | 2 +- source/blender/makesrna/intern/rna_object.c | 4 +- source/blender/makesrna/intern/rna_pose.c | 1 - source/blender/makesrna/intern/rna_sound.c | 16 +- source/blender/makesrna/intern/rna_ui.c | 2 +- source/blender/windowmanager/WM_types.h | 1 + 22 files changed, 341 insertions(+), 97 deletions(-) diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h index e598394cc60..ce182267b93 100644 --- a/source/blender/blenkernel/BKE_library.h +++ b/source/blender/blenkernel/BKE_library.h @@ -45,6 +45,7 @@ void *copy_libblock(void *rt); void id_lib_extern(struct ID *id); void id_us_plus(struct ID *id); +void id_us_min(struct ID *id); int check_for_dupid(struct ListBase *lb, struct ID *id, char *name); int new_id(struct ListBase *lb, struct ID *id, const char *name); diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index d0e4c1a15bc..90ab4e05d44 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -142,6 +142,12 @@ void id_us_plus(ID *id) } } +void id_us_min(ID *id) +{ + if(id) + id->us--; +} + ListBase *wich_libbase(Main *mainlib, short type) { switch( type ) { diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h index c6277f319bc..3d0de795778 100644 --- a/source/blender/editors/include/ED_object.h +++ b/source/blender/editors/include/ED_object.h @@ -35,6 +35,7 @@ struct bContext; struct Base; struct View3D; struct bConstraint; +struct bConstraintChannel; struct KeyBlock; struct Lattice; struct Mesh; @@ -71,8 +72,20 @@ void ED_object_base_init_from_view(struct bContext *C, struct Base *base); int object_data_is_libdata(struct Object *ob); /* constraints */ -struct bConstraint *add_new_constraint (short type); -void add_constraint_to_object (struct bConstraint *con, struct Object *ob); +struct bConstraint *add_new_constraint(short type); +void add_constraint_to_object(struct bConstraint *con, struct Object *ob); + +struct ListBase *get_active_constraints(struct Object *ob); +struct bConstraint *get_active_constraint(struct Object *ob); +struct bConstraintChannel *get_active_constraint_channel(struct Scene *scene, struct Object *ob); + +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); +int ED_object_constraint_delete(struct ReportList *reports, struct Object *ob, struct bConstraint *con); +int ED_object_constraint_move_down(struct ReportList *reports, struct Object *ob, struct bConstraint *con); +int ED_object_constraint_move_up(struct ReportList *reports, struct Object *ob, struct bConstraint *con); /* editlattice.c */ void mouse_lattice(struct bContext *C, short mval[2], int extend); diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index cdb29ecf376..97c2da5297f 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -189,6 +189,8 @@ typedef struct uiLayout uiLayout; #define FTPREVIEW (35<<9) #define NUMABS (36<<9) #define TOGBUT (37<<9) +#define OPTION (38<<9) +#define OPTIONN (39<<9) #define BUTTYPE (63<<9) /* Drawing @@ -579,7 +581,8 @@ uiBlock *uiLayoutFreeBlock(uiLayout *layout); void uiTemplateHeader(uiLayout *layout, struct bContext *C); void uiTemplateHeaderID(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, char *propname, char *newop, char *openop, char *unlinkop); -uiLayout *uiTemplateModifier(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); /* items */ @@ -592,8 +595,8 @@ void uiItemFloatO(uiLayout *layout, char *name, int icon, char *opname, char *pr void uiItemStringO(uiLayout *layout, char *name, int icon, char *opname, char *propname, char *value); void uiItemFullO(uiLayout *layout, char *name, int icon, char *idname, struct IDProperty *properties, int context); -void uiItemR(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, char *propname, int expand, int slider); -void uiItemFullR(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, struct PropertyRNA *prop, int index, int value, int expand, int slider); +void uiItemR(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, char *propname, int expand, int slider, int toggle); +void uiItemFullR(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, struct PropertyRNA *prop, int index, int value, int expand, int slider, int toggle); void uiItemEnumR(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, char *propname, int value); void uiItemsEnumR(uiLayout *layout, struct PointerRNA *ptr, char *propname); diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 0b094f0c8dc..e9a886375c3 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -679,7 +679,7 @@ static void ui_is_but_sel(uiBut *but) value= ui_get_but_val(but); - if( but->type==TOGN || but->type==ICONTOGN) true= 0; + if(ELEM3(but->type, TOGN, ICONTOGN, OPTIONN)) true= 0; if( but->bit ) { lvalue= (int)value; @@ -700,10 +700,12 @@ static void ui_is_but_sel(uiBut *but) case TOG3: case BUT_TOGDUAL: case ICONTOG: + case OPTION: if(value!=but->hardmin) push= 1; break; case ICONTOGN: case TOGN: + case OPTIONN: if(value==0.0) push= 1; break; case ROW: @@ -1509,7 +1511,12 @@ int ui_set_but_string(bContext *C, uiBut *but, const char *str) * custom collection too for bones, vertex groups, .. */ ui_rna_ID_collection(C, but, &ptr, &prop); - if(prop && RNA_property_collection_lookup_string(&ptr, prop, str, &rptr)) { + if(str == NULL || str[0] == '\0') { + memset(&rptr, 0, sizeof(rptr)); + RNA_property_pointer_set(&but->rnapoin, but->rnaprop, rptr); + return 11; + } + else if(prop && RNA_property_collection_lookup_string(&ptr, prop, str, &rptr)) { RNA_property_pointer_set(&but->rnapoin, but->rnaprop, rptr); return 1; } @@ -1989,7 +1996,7 @@ void uiBlockEndAlign(uiBlock *block) int ui_but_can_align(uiBut *but) { - return (but->type != LABEL); + return !ELEM3(but->type, LABEL, OPTION, OPTIONN); } static void ui_block_do_align_but(uiBlock *block, uiBut *first, int nr) diff --git a/source/blender/editors/interface/interface_api.c b/source/blender/editors/interface/interface_api.c index 3cb6678133f..2bbaee857d1 100644 --- a/source/blender/editors/interface/interface_api.c +++ b/source/blender/editors/interface/interface_api.c @@ -89,7 +89,8 @@ void RNA_api_ui_layout(StructRNA *srna) parm= RNA_def_string(func, "property", "", 0, "", "Identifier of property in data."); RNA_def_property_flag(parm, PROP_REQUIRED); RNA_def_boolean(func, "expand", 0, "", "Expand button to show more detail."); - RNA_def_boolean(func, "slider", 0, "", "Use slider for numeric values."); + RNA_def_boolean(func, "slider", 0, "", "Use slider widget for numeric values."); + RNA_def_boolean(func, "toggle", 0, "", "Use toggle widget for boolean values."); func= RNA_def_function(srna, "items_enumR", "uiItemsEnumR"); parm= RNA_def_pointer(func, "data", "AnyType", "", "Data from which to take property."); @@ -198,13 +199,17 @@ void RNA_api_ui_layout(StructRNA *srna) RNA_def_string(func, "unlink", "", 0, "", "Operator identifier to unlink the ID block."); func= RNA_def_function(srna, "template_modifier", "uiTemplateModifier"); - parm= RNA_def_pointer(func, "context", "Context", "", "Current context."); - RNA_def_property_flag(parm, PROP_REQUIRED); parm= RNA_def_pointer(func, "data", "AnyType", "", "Modifier data."); RNA_def_property_flag(parm, PROP_REQUIRED); 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", "AnyType", "", "Constraint data."); + RNA_def_property_flag(parm, PROP_REQUIRED); + 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); diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index ce01bc19856..ec2f960dd14 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -364,7 +364,7 @@ static void ui_apply_but_TOG(bContext *C, uiBlock *block, uiBut *but, uiHandleBu if(value==0.0) push= 1; else push= 0; - if(but->type==TOGN || but->type==ICONTOGN) push= !push; + if(ELEM3(but->type, TOGN, ICONTOGN, OPTIONN)) push= !push; ui_set_but_val(but, (double)push); if(but->type==ICONTOG || but->type==ICONTOGN) ui_check_but(but); } @@ -566,6 +566,8 @@ static void ui_apply_button(bContext *C, uiBlock *block, uiBut *but, uiHandleBut case ICONTOGN: case TOGN: case BUT_TOGDUAL: + case OPTION: + case OPTIONN: ui_apply_but_TOG(C, block, but, data); break; case ROW: @@ -2672,6 +2674,8 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event) case ICONTOGN: case TOGN: case BUT_TOGDUAL: + case OPTION: + case OPTIONN: retval= ui_do_but_TOG(C, but, data, event); break; #if 0 diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c index 16451ec4510..7c739adf1b9 100644 --- a/source/blender/editors/interface/interface_utils.c +++ b/source/blender/editors/interface/interface_utils.c @@ -268,7 +268,7 @@ uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int ind else if(icon) but= uiDefIconTextButR(block, ICONTOG, 0, icon, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL); else - but= uiDefButR(block, TOG, 0, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL); + but= uiDefButR(block, OPTION, 0, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL); break; } case PROP_INT: @@ -338,7 +338,7 @@ void uiDefAutoButsRNA(const bContext *C, uiLayout *layout, PointerRNA *ptr) name= (char*)RNA_property_ui_name(prop); uiItemL(uiLayoutColumn(split, 0), name, 0); - uiItemFullR(uiLayoutColumn(split, 0), "", 0, ptr, prop, -1, 0, 0, 0); + uiItemFullR(uiLayoutColumn(split, 0), "", 0, ptr, prop, -1, 0, 0, 0, 0); } RNA_property_collection_end(&iter); diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index f779022ece5..f4e3a7f2899 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -1830,11 +1830,13 @@ void ui_draw_but(ARegion *ar, uiStyle *style, uiBut *but, rcti *rect) wt= widget_type(UI_WTYPE_NAME); break; case TOGBUT: - wt= widget_type(UI_WTYPE_TOGGLE); - break; case TOG: case TOGN: case TOG3: + wt= widget_type(UI_WTYPE_TOGGLE); + break; + case OPTION: + case OPTIONN: if (!(but->flag & UI_HAS_ICON)) { wt= widget_type(UI_WTYPE_OPTION); but->flag |= UI_TEXT_LEFT; diff --git a/source/blender/editors/object/editconstraint.c b/source/blender/editors/object/editconstraint.c index d0e487f98c7..b2cf3be6229 100644 --- a/source/blender/editors/object/editconstraint.c +++ b/source/blender/editors/object/editconstraint.c @@ -49,17 +49,27 @@ #include "BKE_action.h" #include "BKE_armature.h" #include "BKE_constraint.h" +#include "BKE_context.h" #include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_main.h" #include "BKE_object.h" +#include "BKE_report.h" #include "BKE_utildefines.h" #ifndef DISABLE_PYTHON #include "BPY_extern.h" #endif +#include "WM_api.h" +#include "WM_types.h" + +#include "RNA_access.h" +#include "RNA_define.h" +#include "RNA_enum_types.h" + #include "ED_object.h" +#include "ED_screen.h" #include "object_intern.h" @@ -589,55 +599,6 @@ void ob_clear_constraints (Scene *scene) BIF_undo_push("Clear Constraint(s)"); } -/* Rename the given constraint - * - con already has the new name - */ -void rename_constraint (Object *ob, bConstraint *con, char *oldname) -{ - bConstraint *tcon; - ListBase *conlist= NULL; - int from_object= 0; - char *channame=""; - - /* get context by searching for con (primitive...) */ - for (tcon= ob->constraints.first; tcon; tcon= tcon->next) { - if (tcon==con) - break; - } - - if (tcon) { - conlist= &ob->constraints; - channame= "Object"; - from_object= 1; - } - else if (ob->pose) { - bPoseChannel *pchan; - - for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) { - for (tcon= pchan->constraints.first; tcon; tcon= tcon->next) { - if (tcon==con) - break; - } - if (tcon) - break; - } - - if (tcon) { - conlist= &pchan->constraints; - channame= pchan->name; - } - } - - if (conlist==NULL) { - printf("rename constraint failed\n"); /* should not happen in UI */ - return; - } - - /* first make sure it's a unique name within context */ - unique_constraint_name (con, conlist); -} - - /* ------------- Constraint Sanity Testing ------------------- */ /* checks validity of object pointers, and NULLs, @@ -889,3 +850,237 @@ void childof_const_clearinv (void *conv, void *unused) /* simply clear the matrix */ Mat4One(data->invmat); } + +/***************************** BUTTONS ****************************/ + +/* Rename the given constraint, con already has the new name */ +void ED_object_constraint_rename(Object *ob, bConstraint *con, char *oldname) +{ + bConstraint *tcon; + ListBase *conlist= NULL; + int from_object= 0; + char *channame=""; + + /* get context by searching for con (primitive...) */ + for (tcon= ob->constraints.first; tcon; tcon= tcon->next) { + if (tcon==con) + break; + } + + if (tcon) { + conlist= &ob->constraints; + channame= "Object"; + from_object= 1; + } + else if (ob->pose) { + bPoseChannel *pchan; + + for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) { + for (tcon= pchan->constraints.first; tcon; tcon= tcon->next) { + if (tcon==con) + break; + } + if (tcon) + break; + } + + if (tcon) { + conlist= &pchan->constraints; + channame= pchan->name; + } + } + + if (conlist==NULL) { + printf("rename constraint failed\n"); /* should not happen in UI */ + return; + } + + /* first make sure it's a unique name within context */ + unique_constraint_name (con, conlist); +} + + + + +void ED_object_constraint_set_active(Object *ob, bConstraint *con) +{ + ListBase *lb; + bConstraint *origcon= con; + + /* lets be nice and escape if its active already */ + if(con && (con->flag & CONSTRAINT_ACTIVE)) + return ; + + lb= get_active_constraints(ob); + if(lb == NULL) + return; + + for(con= lb->first; con; con= con->next) { + if(con==origcon) con->flag |= CONSTRAINT_ACTIVE; + else con->flag &= ~CONSTRAINT_ACTIVE; + } + + /* make sure ipowin and buttons shows it */ + if(ob->ipowin==ID_CO) { + // XXX allqueue(REDRAWIPO, ID_CO); + // XXX allspace(REMAKEIPO, 0); + // XXX allqueue(REDRAWNLA, 0); + } + // XXX allqueue(REDRAWBUTSOBJECT, 0); +} + +int ED_object_constraint_delete(ReportList *reports, Object *ob, bConstraint *con) +{ + bConstraintChannel *chan; + ListBase *lb; + + /* remove ipo channel */ + lb= NULL; // XXX get_active_constraint_channels(ob, 0); + if(lb) { + chan = NULL; // XXX get_constraint_channel(lb, con->name); + if(chan) { + if(chan->ipo) chan->ipo->id.us--; + BLI_freelinkN(lb, chan); + } + } + + /* remove constraint itself */ + lb= get_active_constraints(ob); + free_constraint_data(con); + BLI_freelinkN(lb, con); + + ED_object_constraint_set_active(ob, NULL); + + return 1; +} + +int ED_object_constraint_move_down(ReportList *reports, Object *ob, bConstraint *constr) +{ + bConstraint *con; + ListBase *conlist; + + if(constr->next) { + conlist = get_active_constraints(ob); + for(con= conlist->first; con; con= con->next) { + if(con==constr) { + BLI_remlink(conlist, con); + BLI_insertlink(conlist, con->next, con); + return 1; + } + } + } + + return 0; +} + +int ED_object_constraint_move_up(ReportList *reports, Object *ob, bConstraint *constr) +{ + bConstraint *con; + ListBase *conlist; + + if(constr->prev) { + conlist = get_active_constraints(ob); + for(con= conlist->first; con; con= con->next) { + if(con==constr) { + BLI_remlink(conlist, con); + BLI_insertlink(conlist, con->prev->prev, con); + return 1; + } + } + } + + return 0; +} + +/***************************** OPERATORS ****************************/ + +/************************ add constraint operator *********************/ + +static int constraint_add_exec(bContext *C, wmOperator *op) +{ + Scene *scene= CTX_data_scene(C); + Object *ob = CTX_data_active_object(C); + bConstraint *con; + ListBase *list= get_active_constraints(ob); + bPoseChannel *pchan= get_active_posechannel(ob); + int type= RNA_enum_get(op->ptr, "type"); + + con = add_new_constraint(type); + + if(list) { + unique_constraint_name(con, list); + BLI_addtail(list, con); + + if(proxylocked_constraints_owner(ob, pchan)) + con->flag |= CONSTRAINT_PROXY_LOCAL; + + con->flag |= CONSTRAINT_ACTIVE; + for(con= con->prev; con; con= con->prev) + con->flag &= ~CONSTRAINT_ACTIVE; + } + + switch(type) { + case CONSTRAINT_TYPE_CHILDOF: + { + /* if this constraint is being added to a posechannel, make sure + * the constraint gets evaluated in pose-space */ + if(ob->flag & OB_POSEMODE) { + con->ownspace = CONSTRAINT_SPACE_POSE; + con->flag |= CONSTRAINT_SPACEONCE; + } + } + break; + case CONSTRAINT_TYPE_RIGIDBODYJOINT: + { + bRigidBodyJointConstraint *data; + + /* set selected first object as target - moved from new_constraint_data */ + data = (bRigidBodyJointConstraint*)con->data; + + CTX_DATA_BEGIN(C, Object*, selob, selected_objects) { + if(selob != ob) { + data->tar= selob; + break; + } + } + CTX_DATA_END; + } + break; + default: + break; + } + + object_test_constraints(ob); + + if(ob->pose) + update_pose_constraint_flags(ob->pose); + + if(ob->type==OB_ARMATURE) + DAG_object_flush_update(scene, ob, OB_RECALC_DATA|OB_RECALC_OB); + else + DAG_object_flush_update(scene, ob, OB_RECALC_DATA); + + WM_event_add_notifier(C, NC_OBJECT|ND_CONSTRAINT, ob); + + return OPERATOR_FINISHED; +} + +void OBJECT_OT_constraint_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Add Constraint"; + ot->description = "Add a constraint to the active object."; + ot->idname= "OBJECT_OT_constraint_add"; + + /* api callbacks */ + ot->invoke= WM_menu_invoke; + ot->exec= constraint_add_exec; + + ot->poll= ED_operator_object_active; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + RNA_def_enum(ot->srna, "type", constraint_type_items, 0, "Type", ""); +} + diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index 223f2190f4b..ce8bd7287f7 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -88,5 +88,8 @@ void GROUP_OT_objects_remove_active(struct wmOperatorType *ot); void OBJECT_OT_modifier_add(struct wmOperatorType *ot); void OBJECT_OT_multires_subdivide(struct wmOperatorType *ot); +/* editconstraint.c */ +void OBJECT_OT_constraint_add(struct wmOperatorType *ot); + #endif /* ED_OBJECT_INTERN_H */ diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index 339d8bc8252..2e2c16ee6d6 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -368,6 +368,8 @@ void OBJECT_OT_modifier_add(wmOperatorType *ot) RNA_def_enum(ot->srna, "type", modifier_type_items, 0, "Type", ""); } +/****************** multires subdivide operator *********************/ + static int multires_subdivide_exec(bContext *C, wmOperator *op) { Object *ob = CTX_data_active_object(C); diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index f2a020e69a6..9d8247522e1 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -101,6 +101,8 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_modifier_add); WM_operatortype_append(OBJECT_OT_multires_subdivide); + + WM_operatortype_append(OBJECT_OT_constraint_add); } void ED_keymap_object(wmWindowManager *wm) diff --git a/source/blender/editors/space_image/image_header.c b/source/blender/editors/space_image/image_header.c index 2accef990d3..9a61d3a7081 100644 --- a/source/blender/editors/space_image/image_header.c +++ b/source/blender/editors/space_image/image_header.c @@ -150,8 +150,8 @@ static void image_viewmenu(bContext *C, uiLayout *layout, void *arg_unused) uiItemS(layout); - uiItemR(layout, NULL, 0, &spaceptr, "update_automatically", 0, 0); - // XXX if(show_uvedit) uiItemR(layout, NULL, 0, &uvptr, "local_view", 0, 0); // "UV Local View", Numpad / + uiItemR(layout, NULL, 0, &spaceptr, "update_automatically", 0, 0, 0); + // XXX if(show_uvedit) uiItemR(layout, NULL, 0, &uvptr, "local_view", 0, 0, 0); // "UV Local View", Numpad / uiItemS(layout); @@ -234,7 +234,7 @@ static void image_imagemenu(bContext *C, uiLayout *layout, void *arg_unused) uiItemS(layout); - uiItemR(layout, NULL, 0, &spaceptr, "image_painting", 0, 0); + uiItemR(layout, NULL, 0, &spaceptr, "image_painting", 0, 0, 0); /* move to realtime properties panel */ RNA_id_pointer_create(&ima->id, &imaptr); @@ -338,12 +338,12 @@ static void image_uvsmenu(bContext *C, uiLayout *layout, void *arg_unused) RNA_id_pointer_create(&scene->id, &sceneptr); /* create menu */ - uiItemR(layout, NULL, 0, &uvptr, "snap_to_pixels", 0, 0); - uiItemR(layout, NULL, 0, &uvptr, "constrain_to_image_bounds", 0, 0); + uiItemR(layout, NULL, 0, &uvptr, "snap_to_pixels", 0, 0, 0); + uiItemR(layout, NULL, 0, &uvptr, "constrain_to_image_bounds", 0, 0, 0); uiItemS(layout); - uiItemR(layout, NULL, 0, &uvptr, "live_unwrap", 0, 0); + uiItemR(layout, NULL, 0, &uvptr, "live_unwrap", 0, 0, 0); uiItemO(layout, NULL, 0, "UV_OT_unwrap"); uiItemBooleanO(layout, "Unpin", 0, "UV_OT_pin", "clear", 1); uiItemO(layout, NULL, 0, "UV_OT_pin"); @@ -363,7 +363,7 @@ static void image_uvsmenu(bContext *C, uiLayout *layout, void *arg_unused) uiItemS(layout); - uiItemR(layout, NULL, 0, &sceneptr, "proportional_editing", 0, 0); + uiItemR(layout, NULL, 0, &sceneptr, "proportional_editing", 0, 0, 0); uiItemMenuEnumR(layout, NULL, 0, &sceneptr, "proportional_editing_falloff"); uiItemS(layout); diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c index 5b8de93b542..2d623c9c33d 100644 --- a/source/blender/editors/space_view3d/view3d_header.c +++ b/source/blender/editors/space_view3d/view3d_header.c @@ -3359,7 +3359,7 @@ static void view3d_edit_curvemenu(bContext *C, uiLayout *layout, void *arg_unuse uiItemS(layout); - uiItemR(layout, NULL, 0, &sceneptr, "proportional_editing", 0, 0); // |O + uiItemR(layout, NULL, 0, &sceneptr, "proportional_editing", 0, 0, 0); // |O uiItemMenuEnumR(layout, NULL, 0, &sceneptr, "proportional_editing_falloff"); uiItemS(layout); @@ -4533,12 +4533,12 @@ static void view3d_sculpt_menu(bContext *C, uiLayout *layout, void *arg_unused) RNA_pointer_create(&sc->id, &RNA_Sculpt, s, &rna); - uiItemR(layout, NULL, 0, &rna, "symmetry_x", 0, 0); - uiItemR(layout, NULL, 0, &rna, "symmetry_y", 0, 0); - uiItemR(layout, NULL, 0, &rna, "symmetry_z", 0, 0); - uiItemR(layout, NULL, 0, &rna, "lock_x", 0, 0); - uiItemR(layout, NULL, 0, &rna, "lock_y", 0, 0); - uiItemR(layout, NULL, 0, &rna, "lock_z", 0, 0); + uiItemR(layout, NULL, 0, &rna, "symmetry_x", 0, 0, 0); + uiItemR(layout, NULL, 0, &rna, "symmetry_y", 0, 0, 0); + uiItemR(layout, NULL, 0, &rna, "symmetry_z", 0, 0, 0); + uiItemR(layout, NULL, 0, &rna, "lock_x", 0, 0, 0); + uiItemR(layout, NULL, 0, &rna, "lock_y", 0, 0, 0); + uiItemR(layout, NULL, 0, &rna, "lock_z", 0, 0, 0); /* Brush settings */ RNA_pointer_create(&sc->id, &RNA_Brush, s->brush, &rna); @@ -4551,12 +4551,12 @@ static void view3d_sculpt_menu(bContext *C, uiLayout *layout, void *arg_unused) uiItemS(layout); - uiItemR(layout, NULL, 0, &rna, "airbrush", 0, 0); - uiItemR(layout, NULL, 0, &rna, "rake", 0, 0); - uiItemR(layout, NULL, 0, &rna, "anchored", 0, 0); - uiItemR(layout, NULL, 0, &rna, "space", 0, 0); + uiItemR(layout, NULL, 0, &rna, "airbrush", 0, 0, 0); + uiItemR(layout, NULL, 0, &rna, "rake", 0, 0, 0); + uiItemR(layout, NULL, 0, &rna, "anchored", 0, 0, 0); + uiItemR(layout, NULL, 0, &rna, "space", 0, 0, 0); - uiItemR(layout, NULL, 0, &rna, "flip_direction", 0, 0); + uiItemR(layout, NULL, 0, &rna, "flip_direction", 0, 0, 0); } uiBlock *view3d_sculptmenu(bContext *C, ARegion *ar, void *arg_unused) diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h index 2262c73a9af..c679d9fc544 100644 --- a/source/blender/makesrna/RNA_enum_types.h +++ b/source/blender/makesrna/RNA_enum_types.h @@ -33,6 +33,7 @@ extern EnumPropertyItem prop_mode_items[]; extern EnumPropertyItem space_type_items[]; extern EnumPropertyItem region_type_items[]; extern EnumPropertyItem modifier_type_items[]; +extern EnumPropertyItem constraint_type_items[]; extern EnumPropertyItem beztriple_handle_type_items[]; extern EnumPropertyItem beztriple_interpolation_mode_items[]; diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index b0b9e2079f1..02429ffa4bf 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -1558,4 +1558,4 @@ void RNA_def_constraint(BlenderRNA *brna) rna_def_constraint_shrinkwrap(brna); } -#endif +#endif \ No newline at end of file diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index 32af373862b..6baf5083d31 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -49,7 +49,7 @@ static void rna_Object_update(bContext *C, PointerRNA *ptr) DAG_object_flush_update(CTX_data_scene(C), ptr->id.data, OB_RECALC_OB); } -static void rna_Object_scene_update(bContext *C, PointerRNA *ptr) +static void rna_Object_dependency_update(bContext *C, PointerRNA *ptr) { DAG_object_flush_update(CTX_data_scene(C), ptr->id.data, OB_RECALC_OB); DAG_scene_sort(CTX_data_scene(C)); @@ -774,7 +774,7 @@ static StructRNA *rna_def_object(BlenderRNA *brna) RNA_def_property_enum_bitflag_sdna(prop, NULL, "transflag"); RNA_def_property_enum_items(prop, dupli_items); RNA_def_property_ui_text(prop, "Dupli Type", "If not None, object duplication method to use."); - RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, "rna_Object_scene_update"); + RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, "rna_Object_dependency_update"); prop= RNA_def_property(srna, "dupli_frames_no_speed", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "transflag", OB_DUPLINOSPEED); diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c index 5aad710c712..8edcc4c72f4 100644 --- a/source/blender/makesrna/intern/rna_pose.c +++ b/source/blender/makesrna/intern/rna_pose.c @@ -82,7 +82,6 @@ static void rna_def_pose_channel(BlenderRNA *brna) RNA_def_struct_idproperties_func(srna, "rna_PoseChannel_idproperties"); prop= RNA_def_property(srna, "constraints", PROP_COLLECTION, PROP_NONE); - RNA_def_property_collection_sdna(prop, NULL, "constraints", NULL); RNA_def_property_struct_type(prop, "Constraint"); RNA_def_property_ui_text(prop, "Constraints", "Constraints that act on this PoseChannel."); diff --git a/source/blender/makesrna/intern/rna_sound.c b/source/blender/makesrna/intern/rna_sound.c index 2aeb1b984fb..c6515385757 100644 --- a/source/blender/makesrna/intern/rna_sound.c +++ b/source/blender/makesrna/intern/rna_sound.c @@ -64,30 +64,30 @@ static void rna_def_sample(BlenderRNA *brna) prop= RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, prop_sample_type_items); - RNA_def_property_flag(prop, PROP_NOT_EDITABLE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Types", ""); prop= RNA_def_property(srna, "filename", PROP_STRING, PROP_FILEPATH); RNA_def_property_string_sdna(prop, NULL, "name"); - RNA_def_property_flag(prop, PROP_NOT_EDITABLE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Filename", "Full path filename of the sample"); prop= RNA_def_property(srna, "length", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "len"); RNA_def_property_ui_text(prop, "Length", "The length of sample in seconds"); - RNA_def_property_flag(prop, PROP_NOT_EDITABLE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); prop= RNA_def_property(srna, "rate", PROP_INT, PROP_UNSIGNED); RNA_def_property_ui_text(prop, "Rate", "Sample rate in kHz"); - RNA_def_property_flag(prop, PROP_NOT_EDITABLE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); prop= RNA_def_property(srna, "bits", PROP_INT, PROP_UNSIGNED); RNA_def_property_ui_text(prop, "Bits", "Bit-depth of sample"); - RNA_def_property_flag(prop, PROP_NOT_EDITABLE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); prop= RNA_def_property(srna, "channels", PROP_INT, PROP_UNSIGNED); RNA_def_property_ui_text(prop, "Channels", "Number of channels (mono=1; stereo=2)"); - RNA_def_property_flag(prop, PROP_NOT_EDITABLE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); } static void rna_def_soundlistener(BlenderRNA *brna) @@ -117,12 +117,12 @@ static void rna_def_soundlistener(BlenderRNA *brna) prop= RNA_def_property(srna, "num_sounds_blender", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "numsoundsblender"); RNA_def_property_ui_text(prop, "Total Sounds in Blender", "The total number of sounds currently linked and available."); - RNA_def_property_flag(prop, PROP_NOT_EDITABLE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); prop= RNA_def_property(srna, "num_sounds_gameengine", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "numsoundsgameengine"); RNA_def_property_ui_text(prop, "Total Sounds in Game Engine", "The total number of sounds in the Game Engine."); - RNA_def_property_flag(prop, PROP_NOT_EDITABLE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); } #endif diff --git a/source/blender/makesrna/intern/rna_ui.c b/source/blender/makesrna/intern/rna_ui.c index e1bc0de245a..9d3d961c18f 100644 --- a/source/blender/makesrna/intern/rna_ui.c +++ b/source/blender/makesrna/intern/rna_ui.c @@ -151,7 +151,7 @@ static StructRNA *rna_Panel_register(const bContext *C, ReportList *reports, voi PanelType *pt, dummypt = {0}; Panel dummypanel= {0}; PointerRNA dummyptr; - int have_function[2]; + int have_function[3]; /* setup dummy panel & panel type to store static properties in */ dummypanel.type= &dummypt; diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index b96089a05f1..09b81d69ac0 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -196,6 +196,7 @@ typedef struct wmNotifier { #define ND_MODIFIER (23<<16) #define ND_KEYS (24<<16) #define ND_GEOM_DATA (25<<16) +#define ND_CONSTRAINT (26<<16) /* NC_MATERIAL Material */ #define ND_SHADING (30<<16) From 8afd6a9dc54ea40e9f12e746d6e67430613776ec Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 2 Jun 2009 13:03:33 +0000 Subject: [PATCH 017/114] NLA SoC: Added basic info-text drawing on strips The format of these is still rather experimental. --- source/blender/editors/space_nla/nla_draw.c | 41 +++++++++++++++++++- source/blender/editors/space_nla/space_nla.c | 4 ++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index def49021160..78fc4174f95 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -48,6 +48,7 @@ #include "DNA_userdef_types.h" #include "DNA_windowmanager_types.h" #include "DNA_world_types.h" +#include "DNA_vec_types.h" #include "MEM_guardedalloc.h" @@ -128,6 +129,36 @@ static void nla_draw_strip (NlaTrack *nlt, NlaStrip *strip, View2D *v2d, float y gl_round_box_shade(GL_LINE_LOOP, strip->start, yminc, strip->end, ymaxc, 0.0, 0.0, 0.1); } +/* add the relevant text to the cache of text-strings to draw in pixelspace */ +static void nla_draw_strip_text (NlaTrack *nlt, NlaStrip *strip, int index, View2D *v2d, float yminc, float ymaxc) +{ + char str[256]; + rctf rect; + + /* for now, just init the string with a fixed-format */ + if (strip->act) + sprintf(str, "%d | Act: %s | %.2f <-> %.2f", index, strip->act->id.name+2, strip->start, strip->end); + else + sprintf(str, "%d | Act: ", index); + + /* set text colour - if colours (see above) are light, draw black text, otherwise draw white */ + if (strip->flag & (NLASTRIP_FLAG_ACTIVE|NLASTRIP_FLAG_SELECT|NLASTRIP_FLAG_TWEAKUSER)) + glColor3f(0.0f, 0.0f, 0.0f); + else + glColor3f(1.0f, 1.0f, 1.0f); + + /* set bounding-box for text + * - padding of 2 'units' on either side + */ + rect.xmin= strip->start + 2; + rect.ymin= yminc; + rect.xmax= strip->end - 2; + rect.ymax= ymaxc; + + /* add this string to the cache of texts to draw*/ + UI_view2d_text_cache_rectf(v2d, &rect, str); +} + /* ---------------------- */ void draw_nla_main_data (bAnimContext *ac, SpaceNla *snla, ARegion *ar) @@ -175,14 +206,20 @@ void draw_nla_main_data (bAnimContext *ac, SpaceNla *snla, ARegion *ar) { NlaTrack *nlt= (NlaTrack *)ale->data; NlaStrip *strip; + int index; /* draw backdrop? */ // TODO... /* draw each strip in the track (if visible) */ - for (strip=nlt->strips.first; strip; strip= strip->next) { - if (BKE_nlastrip_within_bounds(strip, v2d->cur.xmin, v2d->cur.xmax)) + for (strip=nlt->strips.first, index=1; strip; strip=strip->next, index++) { + if (BKE_nlastrip_within_bounds(strip, v2d->cur.xmin, v2d->cur.xmax)) { + /* draw the visualisation of the strip */ nla_draw_strip(nlt, strip, v2d, yminc, ymaxc); + + /* add the text for this strip to the cache */ + nla_draw_strip_text(nlt, strip, index, v2d, yminc, ymaxc); + } } } break; diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c index 024b23c51b8..1bed72b82fb 100644 --- a/source/blender/editors/space_nla/space_nla.c +++ b/source/blender/editors/space_nla/space_nla.c @@ -246,7 +246,11 @@ static void nla_main_area_draw(const bContext *C, ARegion *ar) /* data */ if (ANIM_animdata_get_context(C, &ac)) { + /* strips and backdrops */ draw_nla_main_data(&ac, snla, ar); + + /* text draw cached, in pixelspace now */ + UI_view2d_text_cache_draw(ar); } /* current frame */ From f6cac5bec7418b58fe250c65293e85a8f0095cb2 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Wed, 3 Jun 2009 11:22:49 +0000 Subject: [PATCH 018/114] NLA SoC: More Drawing Tweaks * Following user feedback, I've increased the separation between normal NLA-tracks and the 'action lines' to try and differentiate them more. This hopefully this will be sufficient, otherwise, I'm going to have to abandon the use of nice, generic channel-identification code for lists of channels... * Improved drawing of 'active' strips. - Now, the active strip (when NOT being 'tweaked') will be simply drawn as a yellow strip + a white border. - The active strip (when BEING 'tweaked') will now be greenish + a white border. The colour here may be tweakable, but we'll see... * Strip extrapolation modes (hold, etc.) are now visualised as rects with alpha and the same colour as the strip they belong to. * Selecting strips now makes them 'active' (and deactivates the others). Only one strip can be active at a time. Still need to figure out precisely how this will work with multiple AnimData blocks + NLA-'tweaking'. * Fixed view-matrix bug introduced in last commit for text drawing. For now, we'll just reset the view matrix after doing that, since it's not too acceptable to move these calls to the end yet, as they should get overlapped by some other editor features (such as the Current Frame indicator) --- source/blender/blenkernel/intern/nla.c | 19 +++ source/blender/editors/space_nla/nla_draw.c | 116 +++++++++++++++--- source/blender/editors/space_nla/nla_select.c | 28 ++++- source/blender/editors/space_nla/space_nla.c | 2 + 4 files changed, 139 insertions(+), 26 deletions(-) diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index cf115cb6faf..6235ec58d40 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -455,6 +455,25 @@ void BKE_nlatrack_sort_strips (NlaTrack *nlt) /* NLA Strips -------------------------------------- */ +/* Find the active NLA-strip within the given track */ +NlaStrip *BKE_nlastrip_find_active (NlaTrack *nlt) +{ + NlaStrip *strip; + + /* sanity check */ + if ELEM(NULL, nlt, nlt->strips.first) + return NULL; + + /* try to find the first active strip */ + for (strip= nlt->strips.first; strip; strip= strip->next) { + if (strip->flag & NLASTRIP_FLAG_ACTIVE) + return strip; + } + + /* none found */ + return NULL; +} + /* Does the given NLA-strip fall within the given bounds (times)? */ short BKE_nlastrip_within_bounds (NlaStrip *strip, float min, float max) { diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index 78fc4174f95..85bf733df87 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "DNA_listBase.h" #include "DNA_anim_types.h" @@ -87,37 +88,103 @@ extern void gl_round_box_shade(int mode, float minx, float miny, float maxx, flo /* *********************************************** */ /* Strips */ -static void nla_draw_strip (NlaTrack *nlt, NlaStrip *strip, View2D *v2d, float yminc, float ymaxc) +static void nla_strip_get_color_inside (AnimData *adt, NlaStrip *strip, float color[3]) { - /* draw extrapolation info first (as backdrop) */ - // TODO... - - /* draw 'inside' of strip itself */ - /* set color of strip - color is used to indicate status here */ - if (strip->flag & NLASTRIP_FLAG_ACTIVE) { - /* tweaking strip should be drawn green when it is acting as the tweaking strip */ + if ((strip->flag & NLASTRIP_FLAG_ACTIVE) && (adt && (adt->flag & ADT_NLA_EDIT_ON))) { + /* active strip should be drawn green when it is acting as the tweaking strip. + * however, this case should be skipped for when not in EditMode... + */ // FIXME: hardcoded temp-hack colors - glColor3f(0.3f, 0.95f, 0.1f); + color[0]= 0.3f; + color[1]= 0.95f; + color[2]= 0.1f; } else if (strip->flag & NLASTRIP_FLAG_TWEAKUSER) { /* alert user that this strip is also used by the tweaking track (this is set when going into * 'editmode' for that strip), since the edits made here may not be what the user anticipated */ // FIXME: hardcoded temp-hack colors - glColor3f(0.85f, 0.0f, 0.0f); + color[0]= 0.85f; + color[1]= 0.0f; + color[2]= 0.0f; } else if (strip->flag & NLASTRIP_FLAG_SELECT) { /* selected strip - use theme color for selected */ - UI_ThemeColor(TH_STRIP_SELECT); + UI_GetThemeColor3fv(TH_STRIP_SELECT, color); } else { /* normal, unselected strip - use standard strip theme color */ - UI_ThemeColor(TH_STRIP); + UI_GetThemeColor3fv(TH_STRIP, color); } +} + +static void nla_draw_strip (AnimData *adt, NlaTrack *nlt, NlaStrip *strip, View2D *v2d, float yminc, float ymaxc) +{ + float color[3]; + + /* get color of strip */ + nla_strip_get_color_inside(adt, strip, color); + + /* draw extrapolation info first (as backdrop) */ + if (strip->extendmode != NLASTRIP_EXTEND_NOTHING) { + /* enable transparency... */ + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + + switch (strip->extendmode) { + /* since this does both sides, only do the 'before' side, and leave the rest to the next case */ + case NLASTRIP_EXTEND_HOLD: + /* only need to draw here if there's no strip before since + * it only applies in such a situation + */ + if (strip->prev) { + /* set the drawing color to the color of the strip, but with very faint alpha */ + glColor4f(color[0], color[1], color[2], 0.15f); + + /* draw the rect to the edge of the screen */ + glBegin(GL_QUADS); + glVertex2f(v2d->cur.xmin, yminc); + glVertex2f(v2d->cur.xmin, ymaxc); + glVertex2f(strip->start, ymaxc); + glVertex2f(strip->start, yminc); + glEnd(); + } + /* no break needed... */ + + /* this only draws after the strip */ + case NLASTRIP_EXTEND_HOLD_FORWARD: + /* only need to try and draw if the next strip doesn't occur immediately after */ + if ((strip->next == NULL) || (IS_EQ(strip->next->start, strip->end)==0)) { + /* set the drawing color to the color of the strip, but this time less faint */ + glColor4f(color[0], color[1], color[2], 0.3f); + + /* draw the rect to the next strip or the edge of the screen */ + glBegin(GL_QUADS); + glVertex2f(strip->end, yminc); + glVertex2f(strip->end, ymaxc); + + if (strip->next) { + glVertex2f(strip->next->start, ymaxc); + glVertex2f(strip->next->start, yminc); + } + else { + glVertex2f(v2d->cur.xmax, ymaxc); + glVertex2f(v2d->cur.xmax, yminc); + } + glEnd(); + } + break; + } + + glDisable(GL_BLEND); + } + + /* draw 'inside' of strip itself */ + glColor3fv(color); uiSetRoundBox(15); /* all corners rounded */ gl_round_box_shade(GL_POLYGON, strip->start, yminc, strip->end, ymaxc, 0.0, 0.5, 0.1); - /* draw strip outline */ + /* draw strip outline - different colors are used here... */ if (strip->flag & NLASTRIP_FLAG_ACTIVE) { /* strip should appear 'sunken', so draw a light border around it */ glColor3f(0.9f, 1.0f, 0.9f); // FIXME: hardcoded temp-hack colors @@ -150,6 +217,7 @@ static void nla_draw_strip_text (NlaTrack *nlt, NlaStrip *strip, int index, View /* set bounding-box for text * - padding of 2 'units' on either side */ + // TODO: make this centered? rect.xmin= strip->start + 2; rect.ymin= yminc; rect.xmax= strip->end - 2; @@ -204,6 +272,7 @@ void draw_nla_main_data (bAnimContext *ac, SpaceNla *snla, ARegion *ar) switch (ale->type) { case ANIMTYPE_NLATRACK: { + AnimData *adt= BKE_animdata_from_id(ale->id); NlaTrack *nlt= (NlaTrack *)ale->data; NlaStrip *strip; int index; @@ -215,7 +284,7 @@ void draw_nla_main_data (bAnimContext *ac, SpaceNla *snla, ARegion *ar) for (strip=nlt->strips.first, index=1; strip; strip=strip->next, index++) { if (BKE_nlastrip_within_bounds(strip, v2d->cur.xmin, v2d->cur.xmax)) { /* draw the visualisation of the strip */ - nla_draw_strip(nlt, strip, v2d, yminc, ymaxc); + nla_draw_strip(adt, nlt, strip, v2d, yminc, ymaxc); /* add the text for this strip to the cache */ nla_draw_strip_text(nlt, strip, index, v2d, yminc, ymaxc); @@ -235,11 +304,14 @@ void draw_nla_main_data (bAnimContext *ac, SpaceNla *snla, ARegion *ar) else glColor4f(0.6f, 0.5f, 0.5f, 0.3f); // greyish-red color - hardcoded for now + /* draw slightly shifted up for greater separation from standard channels, + * but also slightly shorter for some more contrast when viewing the strips + */ glBegin(GL_QUADS); - glVertex2f(v2d->cur.xmin, yminc); - glVertex2f(v2d->cur.xmin, ymaxc); - glVertex2f(v2d->cur.xmax, ymaxc); - glVertex2f(v2d->cur.xmax, yminc); + glVertex2f(v2d->cur.xmin, yminc+NLACHANNEL_SKIP); + glVertex2f(v2d->cur.xmin, ymaxc-NLACHANNEL_SKIP); + glVertex2f(v2d->cur.xmax, ymaxc-NLACHANNEL_SKIP); + glVertex2f(v2d->cur.xmax, yminc+NLACHANNEL_SKIP); glEnd(); glDisable(GL_BLEND); @@ -570,8 +642,12 @@ void draw_nla_channel_list (bAnimContext *ac, SpaceNla *snla, ARegion *ar) glColor3f(0.6f, 0.5f, 0.5f); // greyish-red color - hardcoded for now offset += 7 * indent; - uiSetRoundBox((1|2)); // only on top two corners, to show that this channel sits on top of the preceeding ones - gl_round_box(GL_POLYGON, x+offset, yminc, (float)NLACHANNEL_NAMEWIDTH, ymaxc, 8); + + /* only on top two corners, to show that this channel sits on top of the preceeding ones */ + uiSetRoundBox((1|2)); + + /* draw slightly shifted up vertically to look like it has more separtion from other channels */ + gl_round_box(GL_POLYGON, x+offset, yminc+NLACHANNEL_SKIP, (float)NLACHANNEL_NAMEWIDTH, ymaxc+NLACHANNEL_SKIP, 8); /* clear group value, otherwise we cause errors... */ group = 0; diff --git a/source/blender/editors/space_nla/nla_select.c b/source/blender/editors/space_nla/nla_select.c index 5d9fe5f2a05..0626d9febe4 100644 --- a/source/blender/editors/space_nla/nla_select.c +++ b/source/blender/editors/space_nla/nla_select.c @@ -98,10 +98,16 @@ static short selmodes_to_flagmodes (short sel) * 3) (de)select all - no testing is done; only for use internal tools as normal function... */ +enum { + DESELECT_STRIPS_NOTEST = 0, + DESELECT_STRIPS_TEST, + DESELECT_STRIPS_CLEARACTIVE, +} eDeselectNlaStrips; + /* Deselects strips in the NLA Editor * - This is called by the deselect all operator, as well as other ones! * - * - test: check if select or deselect all + * - test: check if select or deselect all (1) or clear all active (2) * - sel: how to select keyframes * 0 = deselect * 1 = select @@ -121,7 +127,7 @@ static void deselect_nla_strips (bAnimContext *ac, short test, short sel) ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); /* See if we should be selecting or deselecting */ - if (test) { + if (test == DESELECT_STRIPS_TEST) { for (ale= anim_data.first; ale; ale= ale->next) { NlaTrack *nlt= (NlaTrack *)ale->data; NlaStrip *strip; @@ -150,9 +156,11 @@ static void deselect_nla_strips (bAnimContext *ac, short test, short sel) /* apply same selection to all strips */ for (strip= nlt->strips.first; strip; strip= strip->next) { /* set selection */ - ACHANNEL_SET_FLAG(strip, smode, NLASTRIP_FLAG_SELECT); + if (test != DESELECT_STRIPS_CLEARACTIVE) + ACHANNEL_SET_FLAG(strip, smode, NLASTRIP_FLAG_SELECT); /* clear active flag */ + // TODO: for clear active, do we want to limit this to only doing this on a certain set of tracks though? strip->flag &= ~NLASTRIP_FLAG_ACTIVE; } } @@ -173,9 +181,9 @@ static int nlaedit_deselectall_exec(bContext *C, wmOperator *op) /* 'standard' behaviour - check if selected, then apply relevant selection */ if (RNA_boolean_get(op->ptr, "invert")) - deselect_nla_strips(&ac, 0, SELECT_INVERT); + deselect_nla_strips(&ac, DESELECT_STRIPS_NOTEST, SELECT_INVERT); else - deselect_nla_strips(&ac, 1, SELECT_ADD); + deselect_nla_strips(&ac, DESELECT_STRIPS_TEST, SELECT_ADD); /* set notifier that things have changed */ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); @@ -292,7 +300,8 @@ static void mouse_nla_strips (bAnimContext *ac, int mval[2], short select_mode) NlaTrack *nlt= (NlaTrack *)ale->data; nlt->flag |= NLATRACK_SELECTED; - ANIM_set_active_channel(ac->data, ac->datatype, filter, nlt, ANIMTYPE_NLATRACK); + if (nlt->flag & NLATRACK_SELECTED) + ANIM_set_active_channel(ac->data, ac->datatype, filter, nlt, ANIMTYPE_NLATRACK); } } @@ -302,6 +311,13 @@ static void mouse_nla_strips (bAnimContext *ac, int mval[2], short select_mode) if (strip) { select_mode= selmodes_to_flagmodes(select_mode); ACHANNEL_SET_FLAG(strip, select_mode, NLASTRIP_FLAG_SELECT); + + /* if we selected it, we can make it active too + * - we always need to clear the active strip flag though... + */ + deselect_nla_strips(ac, DESELECT_STRIPS_CLEARACTIVE, 0); + if (strip->flag & NLASTRIP_FLAG_SELECT) + strip->flag |= NLASTRIP_FLAG_ACTIVE; } /* free this channel */ diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c index 1bed72b82fb..39579ec96da 100644 --- a/source/blender/editors/space_nla/space_nla.c +++ b/source/blender/editors/space_nla/space_nla.c @@ -253,6 +253,8 @@ static void nla_main_area_draw(const bContext *C, ARegion *ar) UI_view2d_text_cache_draw(ar); } + UI_view2d_view_ortho(C, v2d); + /* current frame */ if (snla->flag & SNLA_DRAWTIME) flag |= DRAWCFRA_UNIT_SECONDS; if ((snla->flag & SNLA_NODRAWCFRANUM)==0) flag |= DRAWCFRA_SHOW_NUMBOX; From 5c21c176fa0a571f3ba47af8ad2c7906a5dc375f Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 5 Jun 2009 05:18:07 +0000 Subject: [PATCH 019/114] NLA SoC: Operators for 'tweaking' strip actions (TAB-Key for both) In this commit, I've introduced the mechanism by which actions already referenced by strips used in the NLA can be edited (or 'tweaked'). To use, simply select a strip you wish to edit, and hit that TAB key to start tweaking that strip's action, and hit TAB again once you're done. What happens when you enter 'tweak mode': 1) The action of the active strip temporarily becomes the 'active action' of the AnimData block. You are now able to edit this in one of the Animation Editors (DopeSheet/Action, Graph Editors) as per normal (i.e. sliding keyframes around, inserting keyframes, etc.). The 'action-line' will therefore get drawn immediately above the active track containing the active strip, so that it's clear that that's what we're editing. 2) All the NLA-tracks (and all the strips within them) that occur after the track that the active strip lived in get disabled while you're in tweakmode. This is equivalent to travelling back to an earlier state in a construction history stack. 3) The active NLA track also gets disabled while in tweakmode, since it would otherwise interfere with the correct functioning of the tweaking for the action of interest. 4) The 'real' active action (i.e. the one displaced by the active strip's action) gets put into temp storage, and will be restored after you exit tweakmode. 5) Any strips which also reference the action being tweaked will get highlighted in red shading to indicate that you may be making some changes to the action which you don't really want to make for the other users too. Please note though, that this is only a rough prototype of this functionality, with some niceties still to come. i.e.: * NLA-tracks after the active track should still get drawn above the 'tweaking action line', but perhaps with different appearance? * Various tools will still need awareness of this to prevent corrupting operations from taking place. How to proceed is still undecided... * When exiting tweak-mode, the strip the action came from still needs some form of syncing with the modified action... there are a few tricky issues here that will need to be solved * Evaluation code doesn't totally take this into account yet... --- Also, fixed a number of bugs with various code (notably selection, and also a few drawing bugs) --- source/blender/blenkernel/BKE_nla.h | 4 + source/blender/blenkernel/intern/anim_sys.c | 15 +- source/blender/blenkernel/intern/nla.c | 100 +++++++++++++ .../blender/editors/animation/anim_channels.c | 12 +- .../blender/editors/animation/anim_filter.c | 118 ++++++++++++++- source/blender/editors/include/ED_anim_api.h | 6 +- source/blender/editors/include/ED_screen.h | 1 + source/blender/editors/screen/screen_ops.c | 6 + .../editors/space_action/action_select.c | 4 +- .../editors/space_graph/graph_select.c | 2 +- .../blender/editors/space_nla/nla_channels.c | 2 +- source/blender/editors/space_nla/nla_draw.c | 81 +++++++---- source/blender/editors/space_nla/nla_edit.c | 137 ++++++++++++++++++ source/blender/editors/space_nla/nla_intern.h | 8 + source/blender/editors/space_nla/nla_ops.c | 56 +++++++ source/blender/editors/space_nla/nla_select.c | 3 +- source/blender/makesdna/DNA_action_types.h | 1 + source/blender/makesdna/DNA_anim_types.h | 11 +- source/blender/makesdna/DNA_scene_types.h | 1 + 19 files changed, 514 insertions(+), 54 deletions(-) diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index 3c3abe11da3..89e5f1af7e1 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -59,9 +59,13 @@ void BKE_nlatrack_set_active(ListBase *tracks, struct NlaTrack *nlt); short BKE_nlatrack_has_space(struct NlaTrack *nlt, float start, float end); void BKE_nlatrack_sort_strips(struct NlaTrack *nlt); +struct NlaStrip *BKE_nlastrip_find_active(struct NlaTrack *nlt); short BKE_nlastrip_within_bounds(struct NlaStrip *strip, float min, float max); void BKE_nla_action_pushdown(struct AnimData *adt); +short BKE_nla_tweakmode_enter(struct AnimData *adt); +void BKE_nla_tweakmode_exit(struct AnimData *adt); + #endif diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 652f733d553..dbc38d2fc7e 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -118,6 +118,9 @@ void BKE_free_animdata (ID *id) /* unlink action (don't free, as it's in its own list) */ if (adt->action) adt->action->id.us--; + /* same goes for the temporarily displaced action */ + if (adt->tmpact) + adt->tmpact->id.us--; /* free nla data */ free_nladata(&adt->nla_tracks); @@ -151,6 +154,7 @@ AnimData *BKE_copy_animdata (AnimData *adt) // XXX review this... it might not be optimal behaviour yet... //id_us_plus((ID *)dadt->action); dadt->action= copy_action(adt->action); + dadt->tmpact= copy_action(adt->action); /* duplicate NLA data */ copy_nladata(&dadt->nla_tracks, &adt->nla_tracks); @@ -595,7 +599,7 @@ static float nlastrip_get_frame (NlaStrip *strip, float cframe, short invert) scale = (float)fabs(strip->scale); /* scale must be positive - we've got a special flag for reversing */ /* length of referenced action */ - actlength = strip->actend-strip->actstart; + actlength = strip->actend - strip->actstart; if (actlength == 0.0f) actlength = 1.0f; /* length of strip */ @@ -630,11 +634,11 @@ static float nlastrip_get_influence (NlaStrip *strip, float cframe) // the +0.0001 factors are to combat rounding errors if (IS_EQ(strip->blendin, 0)==0 && (cframe <= (strip->start + strip->blendin))) { /* there is some blend-in */ - return (float)(fabs(cframe - strip->start) + 0.0001) / (strip->blendin); + return (float)fabs(cframe - strip->start) / (strip->blendin); } else if (IS_EQ(strip->blendout, 0)==0 && (cframe >= (strip->end - strip->blendout))) { /* there is some blend-out */ - return (float)(fabs(strip->end - cframe) + 0.0001) / (strip->blendout); + return (float)fabs(strip->end - cframe) / (strip->blendout); } else { /* in the middle of the strip, we should be full strength */ @@ -674,8 +678,8 @@ static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index NlaEvalStrip *nes; short side= 0; - /* skip if track is muted */ - if (nlt->flag & NLATRACK_MUTED) + /* skip if track is muted or disabled */ + if (nlt->flag & (NLATRACK_MUTED|NLATRACK_DISABLED)) return; /* loop over strips, checking if they fall within the range */ @@ -1104,6 +1108,7 @@ void BKE_animsys_evaluate_animdata (ID *id, AnimData *adt, float ctime, short re * - NLA before Active Action, as Active Action behaves as 'tweaking track' * that overrides 'rough' work in NLA */ + // TODO: need to double check that this all works correctly if ((recalc & ADT_RECALC_ANIM) || (adt->recalc & ADT_RECALC_ANIM)) { /* evaluate NLA data */ diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 6235ec58d40..84f98096364 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -583,4 +583,104 @@ void BKE_nla_action_pushdown (AnimData *adt) } } + +/* Find the active strip + track combo, and set them up as the tweaking track, + * and return if successful or not. + */ +short BKE_nla_tweakmode_enter (AnimData *adt) +{ + NlaTrack *nlt, *activeTrack=NULL; + NlaStrip *strip, *activeStrip=NULL; + + /* verify that data is valid */ + if ELEM(NULL, adt, adt->nla_tracks.first) + return 0; + + /* if block is already in tweakmode, just leave, but we should report + * that this block is in tweakmode (as our returncode) + */ + // FIXME: hopefully the flag is correct! + if (adt->flag & ADT_NLA_EDIT_ON) + return 1; + + /* go over the tracks, finding the active one, and its active strip + * - if we cannot find both, then there's nothing to do + */ + for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) { + /* check if active */ + if (nlt->flag & NLATRACK_ACTIVE) { + /* store reference to this active track */ + activeTrack= nlt; + + /* now try to find active strip */ + activeStrip= BKE_nlastrip_find_active(nlt); + break; + } + } + if ELEM3(NULL, activeTrack, activeStrip, activeStrip->act) { + printf("NLA tweakmode enter - neither active requirement found \n"); + return 0; + } + + /* go over all the tracks up to the active one, tagging each strip that uses the same + * action as the active strip, but leaving everything else alone + */ + for (nlt= activeTrack->prev; nlt; nlt= nlt->prev) { + for (strip= nlt->strips.first; strip; strip= strip->next) { + if (strip->act == activeStrip->act) + strip->flag |= NLASTRIP_FLAG_TWEAKUSER; + else + strip->flag &= ~NLASTRIP_FLAG_TWEAKUSER; // XXX probably don't need to clear this... + } + } + + + /* go over all the tracks after AND INCLUDING the active one, tagging them as being disabled + * - the active track needs to also be tagged, otherwise, it'll overlap with the tweaks going on + */ + for (nlt= activeTrack; nlt; nlt= nlt->next) + nlt->flag |= NLATRACK_DISABLED; + + /* handle AnimData level changes: + * - 'real' active action to temp storage (no need to change user-counts) + * - action of active strip set to be the 'active action' + * - editing-flag for this AnimData block should also get turned on (for more efficient restoring) + */ + adt->tmpact= adt->action; + adt->action= activeStrip->act; + adt->flag |= ADT_NLA_EDIT_ON; + + /* done! */ + return 1; +} + +/* Exit tweakmode for this AnimData block */ +void BKE_nla_tweakmode_exit (AnimData *adt) +{ + NlaTrack *nlt; + + /* verify that data is valid */ + if ELEM(NULL, adt, adt->nla_tracks.first) + return; + + /* hopefully the flag is correct - skip if not on */ + if ((adt->flag & ADT_NLA_EDIT_ON) == 0) + return; + + // TODO: need to sync the user-strip with the new state of the action! + + /* for all NLA-tracks, clear the 'disabled' flag */ + for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) + nlt->flag &= ~NLATRACK_DISABLED; + + /* handle AnimData level changes: + * - 'real' active action is restored from storage + * - storage pointer gets cleared (to avoid having bad notes hanging around) + * - editing-flag for this AnimData block should also get turned off + */ + adt->action= adt->tmpact; + adt->tmpact= NULL; + adt->flag &= ~ADT_NLA_EDIT_ON; +} + /* *************************************************** */ diff --git a/source/blender/editors/animation/anim_channels.c b/source/blender/editors/animation/anim_channels.c index 658bff73978..59fb56f3c35 100644 --- a/source/blender/editors/animation/anim_channels.c +++ b/source/blender/editors/animation/anim_channels.c @@ -90,14 +90,13 @@ /* -------------------------- Exposed API ----------------------------------- */ /* Set the given animation-channel as the active one for the active context */ -void ANIM_set_active_channel (void *data, short datatype, int filter, void *channel_data, short channel_type) +void ANIM_set_active_channel (bAnimContext *ac, void *data, short datatype, int filter, void *channel_data, short channel_type) { ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; /* try to build list of filtered items */ - // XXX we don't need/supply animcontext for now, since in this case, there's nothing really essential there that isn't already covered - ANIM_animdata_filter(NULL, &anim_data, filter, data, datatype); + ANIM_animdata_filter(ac, &anim_data, filter, data, datatype); if (anim_data.first == NULL) return; @@ -151,8 +150,7 @@ void ANIM_set_active_channel (void *data, short datatype, int filter, void *chan case ANIMTYPE_NLATRACK: { NlaTrack *nlt= (NlaTrack *)channel_data; - - ACHANNEL_SET_FLAG(nlt, ACHANNEL_SETFLAG_CLEAR, NLATRACK_ACTIVE); + nlt->flag |= NLATRACK_ACTIVE; } break; } @@ -1474,7 +1472,7 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s /* if group is selected now, make group the 'active' one in the visible list */ if (agrp->flag & AGRP_SELECTED) - ANIM_set_active_channel(ac->data, ac->datatype, filter, agrp, ANIMTYPE_GROUP); + ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, agrp, ANIMTYPE_GROUP); } } break; @@ -1520,7 +1518,7 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s /* if F-Curve is selected now, make F-Curve the 'active' one in the visible list */ if (fcu->flag & FCURVE_SELECTED) - ANIM_set_active_channel(ac->data, ac->datatype, filter, fcu, ANIMTYPE_FCURVE); + ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ANIMTYPE_FCURVE); } } break; diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index ed526bd99a0..32405571b57 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -343,19 +343,33 @@ short ANIM_animdata_get_context (const bContext *C, bAnimContext *ac) /* quick macro to test if AnimData is usable for NLA */ #define ANIMDATA_HAS_NLA(id) ((id)->adt && (id)->adt->nla_tracks.first) -/* quick macro to test for all three avove usability tests, performing the appropriate provided + +/* Quick macro to test for all three avove usability tests, performing the appropriate provided * action for each when the AnimData context is appropriate. * - * Priority order for this goes (most important, to least): NLA, Drivers, Keyframes + * Priority order for this goes (most important, to least): AnimData blocks, NLA, Drivers, Keyframes. + * + * For this to work correctly, a standard set of data needs to be available within the scope that this + * gets called in: + * - ListBase anim_data; + * - bDopeSheet *ads; + * - bAnimListElem *ale; + * - int items; * * - id: ID block which should have an AnimData pointer following it immediately, to use + * - adtOk: line or block of code to execute for AnimData-blocks case (usually ANIMDATA_ADD_ANIMDATA) * - nlaOk: line or block of code to execute for NLA case * - driversOk: line or block of code to execute for Drivers case * - keysOk: line or block of code for Keyframes case */ -#define ANIMDATA_FILTER_CASES(id, nlaOk, driversOk, keysOk) \ +#define ANIMDATA_FILTER_CASES(id, adtOk, nlaOk, driversOk, keysOk) \ {\ - if (ads->filterflag & ADS_FILTER_ONLYNLA) {\ + if (filter_mode & ANIMFILTER_ANIMDATA) {\ + if ((id)->adt) {\ + adtOk\ + }\ + }\ + else if (ads->filterflag & ADS_FILTER_ONLYNLA) {\ if (ANIMDATA_HAS_NLA(id)) {\ nlaOk\ }\ @@ -376,6 +390,18 @@ short ANIM_animdata_get_context (const bContext *C, bAnimContext *ac) } +/* quick macro to add a pointer to an AnimData block as a channel */ +#define ANIMDATA_ADD_ANIMDATA(id) \ + {\ + ale= make_new_animlistelem((id)->adt, ANIMTYPE_ANIMDATA, NULL, ANIMTYPE_NONE, (ID *)id);\ + if (ale) {\ + BLI_addtail(anim_data, ale);\ + items++;\ + }\ + } + + + /* quick macro to test if a anim-channel (F-Curve, Group, etc.) is selected in an acceptable way */ #define ANIMCHANNEL_SELOK(test_func) \ ( !(filter_mode & (ANIMFILTER_SEL|ANIMFILTER_UNSEL)) || \ @@ -713,6 +739,11 @@ static int animdata_filter_nla (ListBase *anim_data, AnimData *adt, int filter_m items++; } } + + /* if we're in NLA-tweakmode, if this track was active, that means that it was the last active one */ + // FIXME: the channels after should still get drawn, just 'differently', and after an active-action channel + if ((adt->flag & ADT_NLA_EDIT_ON) && (nlt->flag & NLATRACK_ACTIVE)) + break; } } } @@ -890,6 +921,7 @@ static int animdata_filter_dopesheet_mats (ListBase *anim_data, bDopeSheet *ads, /* check if ok */ ANIMDATA_FILTER_CASES(ma, + { /* AnimData blocks - do nothing... */ }, ok=1;, ok=1;, ok=1;) @@ -933,6 +965,7 @@ static int animdata_filter_dopesheet_mats (ListBase *anim_data, bDopeSheet *ads, /* add material's animation data */ if (FILTER_MAT_OBJD(ma) || (filter_mode & ANIMFILTER_CURVESONLY)) { ANIMDATA_FILTER_CASES(ma, + { /* AnimData blocks - do nothing... */ }, items += animdata_filter_nla(anim_data, ma->adt, filter_mode, ma, ANIMTYPE_DSMAT, (ID *)ma);, items += animdata_filter_fcurves(anim_data, ma->adt->drivers.first, NULL, ma, ANIMTYPE_DSMAT, filter_mode, (ID *)ma);, items += animdata_filter_action(anim_data, ma->adt->action, filter_mode, ma, ANIMTYPE_DSMAT, (ID *)ma);) @@ -998,6 +1031,7 @@ static int animdata_filter_dopesheet_obdata (ListBase *anim_data, bDopeSheet *ad if ((expanded) || (filter_mode & ANIMFILTER_CURVESONLY)) { /* filtering for channels - nla, drivers, keyframes */ ANIMDATA_FILTER_CASES(iat, + { /* AnimData blocks - do nothing... */ }, items+= animdata_filter_nla(anim_data, iat->adt, filter_mode, iat, type, (ID *)iat);, items+= animdata_filter_fcurves(anim_data, adt->drivers.first, NULL, iat, type, filter_mode, (ID *)iat);, items += animdata_filter_action(anim_data, iat->adt->action, filter_mode, iat, type, (ID *)iat);) @@ -1036,6 +1070,7 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B if (ob->adt) { adt= ob->adt; ANIMDATA_FILTER_CASES(ob, + { /* AnimData blocks - do nothing... */ }, { /* nla */ #if 0 /* include nla-expand widget? */ @@ -1091,6 +1126,7 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B if ((key) && !(ads->filterflag & ADS_FILTER_NOSHAPEKEYS)) { adt= key->adt; ANIMDATA_FILTER_CASES(key, + { /* AnimData blocks - do nothing... */ }, { /* nla */ #if 0 /* include nla-expand widget? */ @@ -1151,6 +1187,7 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B if ((ads->filterflag & ADS_FILTER_NOCAM) == 0) { ANIMDATA_FILTER_CASES(ca, + { /* AnimData blocks - do nothing... */ }, obdata_ok= 1;, obdata_ok= 1;, obdata_ok= 1;) @@ -1163,6 +1200,7 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B if ((ads->filterflag & ADS_FILTER_NOLAM) == 0) { ANIMDATA_FILTER_CASES(la, + { /* AnimData blocks - do nothing... */ }, obdata_ok= 1;, obdata_ok= 1;, obdata_ok= 1;) @@ -1175,6 +1213,7 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B if ((ads->filterflag & ADS_FILTER_NOCUR) == 0) { ANIMDATA_FILTER_CASES(cu, + { /* AnimData blocks - do nothing... */ }, obdata_ok= 1;, obdata_ok= 1;, obdata_ok= 1;) @@ -1216,6 +1255,7 @@ static int animdata_filter_dopesheet_scene (ListBase *anim_data, bDopeSheet *ads if ((ads->filterflag & ADS_FILTER_NOSCE) == 0) { adt= sce->adt; ANIMDATA_FILTER_CASES(sce, + { /* AnimData blocks - do nothing... */ }, { /* nla */ #if 0 /* include nla-expand widget? */ @@ -1266,9 +1306,10 @@ static int animdata_filter_dopesheet_scene (ListBase *anim_data, bDopeSheet *ads /* world */ if ((wo && wo->adt) && !(ads->filterflag & ADS_FILTER_NOWOR)) { - /* Action, Drivers, or NLA for World */ + /* Action, Drivers, or NLA for World */ adt= wo->adt; ANIMDATA_FILTER_CASES(wo, + { /* AnimData blocks - do nothing... */ }, { /* nla */ #if 0 /* include nla-expand widget? */ @@ -1327,6 +1368,7 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int { Scene *sce= (Scene *)ads->source; Base *base; + bAnimListElem *ale; int items = 0; /* check that we do indeed have a scene */ @@ -1342,11 +1384,25 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int /* check filtering-flags if ok */ ANIMDATA_FILTER_CASES(sce, + { + /* 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(sce); + sceOk=0; + }, sceOk= !(ads->filterflag & ADS_FILTER_NOSCE);, sceOk= !(ads->filterflag & ADS_FILTER_NOSCE);, sceOk= !(ads->filterflag & ADS_FILTER_NOSCE);) if (sce->world) { ANIMDATA_FILTER_CASES(sce->world, + { + /* 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(sce->world); + worOk=0; + }, worOk= !(ads->filterflag & ADS_FILTER_NOWOR);, worOk= !(ads->filterflag & ADS_FILTER_NOWOR);, worOk= !(ads->filterflag & ADS_FILTER_NOWOR);) @@ -1395,12 +1451,26 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int actOk= 0; keyOk= 0; ANIMDATA_FILTER_CASES(ob, + { + /* 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(ob); + actOk=0; + }, actOk= 1;, actOk= 1;, actOk= 1;) if (key) { /* shapekeys */ ANIMDATA_FILTER_CASES(key, + { + /* 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(key); + keyOk=0; + }, keyOk= 1;, keyOk= 1;, keyOk= 1;) @@ -1419,6 +1489,13 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int /* if material has relevant animation data, break */ ANIMDATA_FILTER_CASES(ma, + { + /* 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(ma); + matOk=0; + }, matOk= 1;, matOk= 1;, matOk= 1;) @@ -1435,6 +1512,13 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int Camera *ca= (Camera *)ob->data; dataOk= 0; ANIMDATA_FILTER_CASES(ca, + if ((ads->filterflag & ADS_FILTER_NOCAM)==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(ca); + dataOk=0; + }, dataOk= !(ads->filterflag & ADS_FILTER_NOCAM);, dataOk= !(ads->filterflag & ADS_FILTER_NOCAM);, dataOk= !(ads->filterflag & ADS_FILTER_NOCAM);) @@ -1445,11 +1529,35 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int Lamp *la= (Lamp *)ob->data; dataOk= 0; ANIMDATA_FILTER_CASES(la, + if ((ads->filterflag & ADS_FILTER_NOLAM)==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(la); + dataOk=0; + }, dataOk= !(ads->filterflag & ADS_FILTER_NOLAM);, dataOk= !(ads->filterflag & ADS_FILTER_NOLAM);, dataOk= !(ads->filterflag & ADS_FILTER_NOLAM);) } break; + case OB_CURVE: /* ------- Curve ---------- */ + { + Curve *cu= (Curve *)ob->data; + dataOk= 0; + ANIMDATA_FILTER_CASES(cu, + if ((ads->filterflag & ADS_FILTER_NOCUR)==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(cu); + dataOk=0; + }, + dataOk= !(ads->filterflag & ADS_FILTER_NOCUR);, + dataOk= !(ads->filterflag & ADS_FILTER_NOCUR);, + dataOk= !(ads->filterflag & ADS_FILTER_NOCUR);) + } + break; default: /* --- other --- */ dataOk= 0; break; diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index cdd8b5c368c..dcaabb4b369 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -107,6 +107,7 @@ typedef struct bAnimListElem { // XXX was ACTTYPE_* typedef enum eAnim_ChannelType { ANIMTYPE_NONE= 0, + ANIMTYPE_ANIMDATA, ANIMTYPE_SPECIALDATA, ANIMTYPE_SCENE, @@ -162,6 +163,7 @@ typedef enum eAnimFilter_Flags { ANIMFILTER_ACTGROUPED = (1<<6), /* belongs to the active actiongroup */ ANIMFILTER_CURVEVISIBLE = (1<<7), /* F-Curve is visible for editing/viewing in Graph Editor */ ANIMFILTER_ACTIVE = (1<<8), /* channel should be 'active' */ // FIXME: this is only relevant for F-Curves for now + ANIMFILTER_ANIMDATA = (1<<9), /* only return the underlying AnimData blocks (not the tracks, etc.) data comes from */ } eAnimFilter_Flags; @@ -254,7 +256,7 @@ short ANIM_animdata_context_getdata(bAnimContext *ac); void ANIM_deselect_anim_channels(void *data, short datatype, short test, short sel); /* Set the 'active' channel of type channel_type, in the given action */ -void ANIM_set_active_channel(void *data, short datatype, int filter, void *channel_data, short channel_type); +void ANIM_set_active_channel(bAnimContext *ac, void *data, short datatype, int filter, void *channel_data, short channel_type); /* --------------- Settings and/or Defines -------------- */ @@ -308,6 +310,8 @@ void ipo_rainbow(int cur, int tot, float *out); /* ------------- NLA-Mapping ----------------------- */ /* anim_draw.c */ +// XXX these are soon to be depreceated? + /* Obtain the Object providing NLA-scaling for the given channel if applicable */ struct Object *ANIM_nla_mapping_get(bAnimContext *ac, bAnimListElem *ale); diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index c2beb34e7b5..e3b6572c03a 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -118,6 +118,7 @@ int ED_operator_node_active(struct bContext *C); int ED_operator_ipo_active(struct bContext *C); int ED_operator_sequencer_active(struct bContext *C); int ED_operator_image_active(struct bContext *C); +int ED_operator_nla_active(struct bContext *C); int ED_operator_object_active(struct bContext *C); int ED_operator_editmesh(struct bContext *C); diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index be952558b6c..db1a39ed056 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -164,6 +164,7 @@ int ED_operator_node_active(bContext *C) return 0; } +// XXX rename int ED_operator_ipo_active(bContext *C) { return ed_spacetype_test(C, SPACE_IPO); @@ -179,6 +180,11 @@ int ED_operator_image_active(bContext *C) return ed_spacetype_test(C, SPACE_IMAGE); } +int ED_operator_nla_active(bContext *C) +{ + return ed_spacetype_test(C, SPACE_NLA); +} + int ED_operator_object_active(bContext *C) { return NULL != CTX_data_active_object(C); diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c index f64cd0f707c..d8ed3fd1068 100644 --- a/source/blender/editors/space_action/action_select.c +++ b/source/blender/editors/space_action/action_select.c @@ -862,13 +862,13 @@ static void mouse_action_keys (bAnimContext *ac, int mval[2], short select_mode, bActionGroup *agrp= ale->data; agrp->flag |= AGRP_SELECTED; - ANIM_set_active_channel(ac->data, ac->datatype, filter, agrp, ANIMTYPE_GROUP); + ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, agrp, ANIMTYPE_GROUP); } else if (ale->type == ANIMTYPE_FCURVE) { FCurve *fcu= ale->data; fcu->flag |= FCURVE_SELECTED; - ANIM_set_active_channel(ac->data, ac->datatype, filter, fcu, ANIMTYPE_FCURVE); + ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ANIMTYPE_FCURVE); } } else if (ac->datatype == ANIMCONT_GPENCIL) { diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c index bb923ca6f95..21320b60ead 100644 --- a/source/blender/editors/space_graph/graph_select.c +++ b/source/blender/editors/space_graph/graph_select.c @@ -722,7 +722,7 @@ static void mouse_graph_keys (bAnimContext *ac, int mval[], short select_mode, s /* set active F-Curve (NOTE: sync the filter flags with findnearest_fcurve_vert) */ if (fcu->flag & FCURVE_SELECTED) { filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_CURVESONLY); - ANIM_set_active_channel(ac->data, ac->datatype, filter, fcu, ANIMTYPE_FCURVE); + ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ANIMTYPE_FCURVE); } } diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c index a839ccbf3d6..8db85ffa0b1 100644 --- a/source/blender/editors/space_nla/nla_channels.c +++ b/source/blender/editors/space_nla/nla_channels.c @@ -349,7 +349,7 @@ static void mouse_nla_channels (bAnimContext *ac, float x, int channel_index, sh /* if NLA-Track is selected now, make NLA-Track the 'active' one in the visible list */ if (nlt->flag & NLATRACK_SELECTED) - ANIM_set_active_channel(ac->data, ac->datatype, filter, nlt, ANIMTYPE_NLATRACK); + ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, nlt, ANIMTYPE_NLATRACK); } } break; diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index 85bf733df87..6c4c64ea272 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -137,7 +137,7 @@ static void nla_draw_strip (AnimData *adt, NlaTrack *nlt, NlaStrip *strip, View2 /* only need to draw here if there's no strip before since * it only applies in such a situation */ - if (strip->prev) { + if (strip->prev == NULL) { /* set the drawing color to the color of the strip, but with very faint alpha */ glColor4f(color[0], color[1], color[2], 0.15f); @@ -563,15 +563,20 @@ void draw_nla_channel_list (bAnimContext *ac, SpaceNla *snla, ARegion *ar) else special= ICON_LAYER_USED; - if (nlt->flag & NLATRACK_MUTED) - mute = ICON_MUTE_IPO_ON; - else - mute = ICON_MUTE_IPO_OFF; - - if (EDITABLE_NLT(nlt)) - protect = ICON_UNLOCKED; - else - protect = ICON_LOCKED; + /* if this track is active and we're tweaking it, don't draw these toggles */ + // TODO: need a special macro for this... + if ( ((nlt->flag & NLATRACK_ACTIVE) && (nlt->flag & NLATRACK_DISABLED)) == 0 ) + { + if (nlt->flag & NLATRACK_MUTED) + mute = ICON_MUTE_IPO_ON; + else + mute = ICON_MUTE_IPO_OFF; + + if (EDITABLE_NLT(nlt)) + protect = ICON_UNLOCKED; + else + protect = ICON_LOCKED; + } sel = SEL_NLT(nlt); strcpy(name, nlt->name); @@ -636,18 +641,29 @@ void draw_nla_channel_list (bAnimContext *ac, SpaceNla *snla, ARegion *ar) } else if (group == 5) { /* Action Line */ - if (ale->data) - glColor3f(0.8f, 0.2f, 0.0f); // reddish color - hardcoded for now - else - glColor3f(0.6f, 0.5f, 0.5f); // greyish-red color - hardcoded for now - + AnimData *adt= BKE_animdata_from_id(ale->id); + + // TODO: if tweaking some action, use the same color as for the tweaked track (quick hack done for now) + if (adt && (adt->flag & ADT_NLA_EDIT_ON)) { + // greenish color (same as tweaking strip) - hardcoded for now + glColor3f(0.3f, 0.95f, 0.1f); + } + else { + if (ale->data) + glColor3f(0.8f, 0.2f, 0.0f); // reddish color - hardcoded for now + else + glColor3f(0.6f, 0.5f, 0.5f); // greyish-red color - hardcoded for now + } + offset += 7 * indent; /* only on top two corners, to show that this channel sits on top of the preceeding ones */ uiSetRoundBox((1|2)); - /* draw slightly shifted up vertically to look like it has more separtion from other channels */ - gl_round_box(GL_POLYGON, x+offset, yminc+NLACHANNEL_SKIP, (float)NLACHANNEL_NAMEWIDTH, ymaxc+NLACHANNEL_SKIP, 8); + /* draw slightly shifted up vertically to look like it has more separtion from other channels, + * but we then need to slightly shorten it so that it doesn't look like it overlaps + */ + gl_round_box(GL_POLYGON, x+offset, yminc+NLACHANNEL_SKIP, (float)NLACHANNEL_NAMEWIDTH, ymaxc+NLACHANNEL_SKIP-1, 8); /* clear group value, otherwise we cause errors... */ group = 0; @@ -709,20 +725,29 @@ void draw_nla_channel_list (bAnimContext *ac, SpaceNla *snla, ARegion *ar) UI_icon_draw((float)(NLACHANNEL_NAMEWIDTH-offset), ydatac, mute); } - /* draw action 'push-down' - only for NLA-Action lines, and only when there's an action */ + /* draw NLA-action line 'status-icons' - only when there's an action */ if ((ale->type == ANIMTYPE_NLAACTION) && (ale->data)) { + AnimData *adt= BKE_animdata_from_id(ale->id); + offset += 16; - /* XXX firstly draw a little rect to help identify that it's different from the toggles */ - glBegin(GL_LINE_LOOP); - glVertex2f((float)NLACHANNEL_NAMEWIDTH-offset-1, y-7); - glVertex2f((float)NLACHANNEL_NAMEWIDTH-offset-1, y+9); - glVertex2f((float)NLACHANNEL_NAMEWIDTH-1, y+9); - glVertex2f((float)NLACHANNEL_NAMEWIDTH-1, y-7); - glEnd(); // GL_LINES - - /* now draw the icon */ - UI_icon_draw((float)NLACHANNEL_NAMEWIDTH-offset, ydatac, ICON_FREEZE); + /* now draw some indicator icons */ + if ((adt) && (adt->flag & ADT_NLA_EDIT_ON)) { + /* 'tweaking action' - not a button */ + UI_icon_draw((float)NLACHANNEL_NAMEWIDTH-offset, ydatac, ICON_EDIT); + } + else { + /* XXX firstly draw a little rect to help identify that it's different from the toggles */ + glBegin(GL_LINE_LOOP); + glVertex2f((float)NLACHANNEL_NAMEWIDTH-offset-1, y-7); + glVertex2f((float)NLACHANNEL_NAMEWIDTH-offset-1, y+9); + glVertex2f((float)NLACHANNEL_NAMEWIDTH-1, y+9); + glVertex2f((float)NLACHANNEL_NAMEWIDTH-1, y-7); + glEnd(); // GL_LINES + + /* 'push down' icon for normal active-actions */ + UI_icon_draw((float)NLACHANNEL_NAMEWIDTH-offset, ydatac, ICON_FREEZE); + } } glDisable(GL_BLEND); diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index ce9ae7de7a9..f7053957667 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -68,6 +68,143 @@ #include "nla_intern.h" // own include /* *********************************************** */ +/* General Editing */ + +/* ******************** Tweak-Mode Operators ***************************** */ +/* 'Tweak mode' allows the action referenced by the active NLA-strip to be edited + * as if it were the normal Active-Action of its AnimData block. + */ + +static int nlaedit_enable_tweakmode_exec (bContext *C, wmOperator *op) +{ + bAnimContext ac; + + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + int ok=0; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* get a list of the AnimData blocks being shown in the NLA */ + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_ANIMDATA); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* if no blocks, popup error? */ + if (anim_data.first == NULL) { + BKE_report(op->reports, RPT_ERROR, "No AnimData blocks to enter tweakmode for"); + return OPERATOR_CANCELLED; + } + + /* for each AnimData block with NLA-data, try setting it in tweak-mode */ + for (ale= anim_data.first; ale; ale= ale->next) { + AnimData *adt= ale->data; + + /* try entering tweakmode if valid */ + ok += BKE_nla_tweakmode_enter(adt); + } + + /* free temp data */ + BLI_freelistN(&anim_data); + + /* if we managed to enter tweakmode on at least one AnimData block, + * set the flag for this in the active scene and send notifiers + */ + if (ac.scene && ok) { + /* set editing flag */ + ac.scene->flag |= SCE_NLA_EDIT_ON; + + /* set notifier that things have changed */ + ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); + WM_event_add_notifier(C, NC_SCENE, NULL); + } + + /* done */ + return OPERATOR_FINISHED; +} + +void NLAEDIT_OT_tweakmode_enter (wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Enter Tweak Mode"; + ot->idname= "NLAEDIT_OT_tweakmode_enter"; + ot->description= "Enter tweaking mode for the action referenced by the active strip."; + + /* api callbacks */ + ot->exec= nlaedit_enable_tweakmode_exec; + ot->poll= nlaop_poll_tweakmode_off; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +/* ------------- */ + +static int nlaedit_disable_tweakmode_exec (bContext *C, wmOperator *op) +{ + bAnimContext ac; + + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* get a list of the AnimData blocks being shown in the NLA */ + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_ANIMDATA); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* if no blocks, popup error? */ + if (anim_data.first == NULL) { + BKE_report(op->reports, RPT_ERROR, "No AnimData blocks to enter tweakmode for"); + return OPERATOR_CANCELLED; + } + + /* for each AnimData block with NLA-data, try exitting tweak-mode */ + for (ale= anim_data.first; ale; ale= ale->next) { + AnimData *adt= ale->data; + + /* try entering tweakmode if valid */ + BKE_nla_tweakmode_exit(adt); + } + + /* free temp data */ + BLI_freelistN(&anim_data); + + /* if we managed to enter tweakmode on at least one AnimData block, + * set the flag for this in the active scene and send notifiers + */ + if (ac.scene) { + /* clear editing flag */ + ac.scene->flag &= ~SCE_NLA_EDIT_ON; + + /* set notifier that things have changed */ + ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); + WM_event_add_notifier(C, NC_SCENE, NULL); + } + + /* done */ + return OPERATOR_FINISHED; +} + +void NLAEDIT_OT_tweakmode_exit (wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Exit Tweak Mode"; + ot->idname= "NLAEDIT_OT_tweakmode_exit"; + ot->description= "Exit tweaking mode for the action referenced by the active strip."; + + /* api callbacks */ + ot->exec= nlaedit_disable_tweakmode_exec; + ot->poll= nlaop_poll_tweakmode_on; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} /* *********************************************** */ diff --git a/source/blender/editors/space_nla/nla_intern.h b/source/blender/editors/space_nla/nla_intern.h index 448b823bd4b..a7188a7cccd 100644 --- a/source/blender/editors/space_nla/nla_intern.h +++ b/source/blender/editors/space_nla/nla_intern.h @@ -76,6 +76,9 @@ void NLAEDIT_OT_click_select(wmOperatorType *ot); /* **************************************** */ /* nla_edit.c */ +void NLAEDIT_OT_tweakmode_enter(wmOperatorType *ot); +void NLAEDIT_OT_tweakmode_exit(wmOperatorType *ot); + /* **************************************** */ /* nla_channels.c */ @@ -85,6 +88,11 @@ void NLA_OT_channels_click(wmOperatorType *ot); /* **************************************** */ /* nla_ops.c */ +int nlaop_poll_tweakmode_off(bContext *C); +int nlaop_poll_tweakmode_on (bContext *C); + +/* --- */ + void nla_operatortypes(void); void nla_keymap(wmWindowManager *wm); diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c index 167686c99f9..057e4b05656 100644 --- a/source/blender/editors/space_nla/nla_ops.c +++ b/source/blender/editors/space_nla/nla_ops.c @@ -65,6 +65,51 @@ #include "nla_intern.h" // own include +/* ************************** poll callbacks for operators **********************************/ + +/* tweakmode is NOT enabled */ +int nlaop_poll_tweakmode_off (bContext *C) +{ + Scene *scene; + + /* for now, we check 2 things: + * 1) active editor must be NLA + * 2) tweakmode is currently set as a 'per-scene' flag + * so that it will affect entire NLA data-sets, + * but not all AnimData blocks will be in tweakmode for + * various reasons + */ + if (ED_operator_nla_active(C) == 0) + return 0; + + scene= CTX_data_scene(C); + if ((scene == NULL) || (scene->flag & SCE_NLA_EDIT_ON)) + return 0; + + return 1; +} + +/* tweakmode IS enabled */ +int nlaop_poll_tweakmode_on (bContext *C) +{ + Scene *scene; + + /* for now, we check 2 things: + * 1) active editor must be NLA + * 2) tweakmode is currently set as a 'per-scene' flag + * so that it will affect entire NLA data-sets, + * but not all AnimData blocks will be in tweakmode for + * various reasons + */ + if (ED_operator_nla_active(C) == 0) + return 0; + + scene= CTX_data_scene(C); + if ((scene == NULL) || !(scene->flag & SCE_NLA_EDIT_ON)) + return 0; + + return 1; +} /* ************************** registration - operator types **********************************/ @@ -77,6 +122,10 @@ void nla_operatortypes(void) /* select */ WM_operatortype_append(NLAEDIT_OT_click_select); WM_operatortype_append(NLAEDIT_OT_select_all_toggle); + + /* edit */ + WM_operatortype_append(NLAEDIT_OT_tweakmode_enter); + WM_operatortype_append(NLAEDIT_OT_tweakmode_exit); } /* ************************** registration - keymaps **********************************/ @@ -130,6 +179,13 @@ static void nla_keymap_main (wmWindowManager *wm, ListBase *keymap) WM_keymap_add_item(keymap, "NLAEDIT_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0); RNA_boolean_set(WM_keymap_add_item(keymap, "NLAEDIT_OT_select_all_toggle", IKEY, KM_PRESS, KM_CTRL, 0)->ptr, "invert", 1); + /* editing */ + /* tweakmode + * - enter and exit are separate operators with the same hotkey... + * This works as they use different poll()'s + */ + WM_keymap_add_item(keymap, "NLAEDIT_OT_tweakmode_enter", TABKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "NLAEDIT_OT_tweakmode_exit", TABKEY, KM_PRESS, 0, 0); /* transform system */ //transform_keymap_for_space(wm, keymap, SPACE_NLA); diff --git a/source/blender/editors/space_nla/nla_select.c b/source/blender/editors/space_nla/nla_select.c index 0626d9febe4..2e3d5572711 100644 --- a/source/blender/editors/space_nla/nla_select.c +++ b/source/blender/editors/space_nla/nla_select.c @@ -300,8 +300,7 @@ static void mouse_nla_strips (bAnimContext *ac, int mval[2], short select_mode) NlaTrack *nlt= (NlaTrack *)ale->data; nlt->flag |= NLATRACK_SELECTED; - if (nlt->flag & NLATRACK_SELECTED) - ANIM_set_active_channel(ac->data, ac->datatype, filter, nlt, ANIMTYPE_NLATRACK); + ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, nlt, ANIMTYPE_NLATRACK); } } diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index e41ab5ac492..a566f733978 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -269,6 +269,7 @@ typedef enum eAction_Flags { /* flags for evaluation/editing */ ACT_MUTED = (1<<9), ACT_PROTECTED = (1<<10), + ACT_DISABLED = (1<<11), } eAction_Flags; diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h index ffc1561e7ab..c19318629f6 100644 --- a/source/blender/makesdna/DNA_anim_types.h +++ b/source/blender/makesdna/DNA_anim_types.h @@ -506,6 +506,9 @@ enum { NLATRACK_SOLO = (1<<3), /* track's settings (and strips) cannot be edited (to guard against unwanted changes) */ NLATRACK_PROTECTED = (1<<4), + + /* track is not allowed to execute, usually as result of tweaking being enabled (internal flag) */ + NLATRACK_DISABLED = (1<<10), } eNlaTrack_Flag; @@ -648,11 +651,15 @@ typedef struct AnimOverride { * blocks may override local settings. * * This datablock should be placed immediately after the ID block where it is used, so that - * the code which retrieves this data can do so in an easier manner. See blenkernel/internal/anim_sys.c for details. + * the code which retrieves this data can do so in an easier manner. See blenkernel/intern/anim_sys.c for details. */ typedef struct AnimData { /* active action - acts as the 'tweaking track' for the NLA */ - bAction *action; + bAction *action; + /* temp-storage for the 'real' active action (i.e. the one used before the tweaking-action + * took over to be edited in the Animation Editors) + */ + bAction *tmpact; /* remapping-info for active action - should only be used if needed * (for 'foreign' actions that aren't working correctly) */ diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 6f88a98fee8..8acefdad9a2 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -832,6 +832,7 @@ typedef struct Scene { /* sce->flag */ #define SCE_DS_SELECTED (1<<0) #define SCE_DS_COLLAPSED (1<<1) +#define SCE_NLA_EDIT_ON (1<<2) /* return flag next_object function */ From 308b567e9c2c36ddb3e9571e4d064a8954f83607 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 5 Jun 2009 11:51:27 +0000 Subject: [PATCH 020/114] NLA SoC: NLA-Evaluation Bugfixes * Fixed an evil bug where the last frame of a strip was always incorrectly evaluated. This was because these frames were not being included in the strip's 'range' as defined by the IN_RANGE() testing macro, which only considers the given range as an open interval (i.e. non-inclusive of boundary points). I've added a new macro, IN_RANGE_INCL(), which is inclusive of boundary points, since this is a common test in many other parts of the code. * When an AnimData block is in 'tweaking' mode, the tracks following (and including the active track) are now correctly skipped during evaluation. * Finished coding the option of setting a single NLA-track per NLA-block to play 'solo' (i.e. only that track is enabled for evaluation). To enable this, simply click on one of the grey 'dots' beside the NLA-track names, turning this dot yellow. The 'yellow' dot means that the track will play by itself (even the 'active action' gets silenced). Only one track per AnimData block can play solo at a time. To disable, simply click on the 'yellow' dot again. NOTE: this currently uses the View3D layer-status icons. We probably need some special ones for these later (coloured vs grey star?) * Also (not related to evaluation) made the selection operators for the NLA Editor only work when not in tweaking mode, since in tweaking mode they can potentially result in data being resolved inappropriately when leaving tweaking mode. --- source/blender/blenkernel/BKE_nla.h | 4 +++ source/blender/blenkernel/BKE_utildefines.h | 1 + source/blender/blenkernel/intern/anim_sys.c | 34 +++++++++++++------ source/blender/blenkernel/intern/nla.c | 32 +++++++++++++++++ .../blender/editors/space_nla/nla_channels.c | 19 ++++++++++- source/blender/editors/space_nla/nla_intern.h | 3 ++ source/blender/editors/space_nla/nla_select.c | 4 +-- 7 files changed, 84 insertions(+), 13 deletions(-) diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index 89e5f1af7e1..da824fd2093 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -56,12 +56,16 @@ struct NlaStrip *add_nlastrip_to_stack(struct AnimData *adt, struct bAction *act struct NlaTrack *BKE_nlatrack_find_active(ListBase *tracks); void BKE_nlatrack_set_active(ListBase *tracks, struct NlaTrack *nlt); +void BKE_nlatrack_solo_toggle(struct AnimData *adt, struct NlaTrack *nlt); + short BKE_nlatrack_has_space(struct NlaTrack *nlt, float start, float end); void BKE_nlatrack_sort_strips(struct NlaTrack *nlt); + struct NlaStrip *BKE_nlastrip_find_active(struct NlaTrack *nlt); short BKE_nlastrip_within_bounds(struct NlaStrip *strip, float min, float max); + void BKE_nla_action_pushdown(struct AnimData *adt); short BKE_nla_tweakmode_enter(struct AnimData *adt); diff --git a/source/blender/blenkernel/BKE_utildefines.h b/source/blender/blenkernel/BKE_utildefines.h index 6584af085cd..0bed2c095e2 100644 --- a/source/blender/blenkernel/BKE_utildefines.h +++ b/source/blender/blenkernel/BKE_utildefines.h @@ -128,6 +128,7 @@ #define IS_EQT(a, b, c) ((a > b)? (((a-b) <= c)? 1:0) : ((((b-a) <= c)? 1:0))) #define IN_RANGE(a, b, c) ((b < c)? ((bflag & (NLATRACK_MUTED|NLATRACK_DISABLED)) - return; - /* loop over strips, checking if they fall within the range */ for (strip= nlt->strips.first; strip; strip= strip->next) { /* check if current time occurs within this strip */ - if (IN_RANGE(ctime, strip->start, strip->end)) { + if (IN_RANGE_INCL(ctime, strip->start, strip->end)) { /* this strip is active, so try to use it */ estrip= strip; side= NES_TIME_WITHIN; @@ -1013,8 +1009,21 @@ static void animsys_evaluate_nla (PointerRNA *ptr, AnimData *adt, float ctime) NlaEvalStrip *nes; /* 1. get the stack of strips to evaluate at current time (influence calculated here) */ - for (nlt=adt->nla_tracks.first; nlt; nlt=nlt->next, track_index++) + for (nlt=adt->nla_tracks.first; nlt; nlt=nlt->next, track_index++) { + /* if tweaking is on and this strip is the tweaking track, stop on this one */ + if ((adt->flag & ADT_NLA_EDIT_ON) && (nlt->flag & NLATRACK_DISABLED)) + break; + + /* skip if we're only considering a track tagged 'solo' */ + if ((adt->flag & ADT_NLA_SOLO_TRACK) && (nlt->flag & NLATRACK_SOLO)==0) + continue; + /* skip if track is muted */ + if (nlt->flag & NLATRACK_MUTED) + continue; + + /* otherwise, get strip to evaluate for this channel */ nlatrack_ctime_get_strip(&estrips, nlt, track_index, ctime); + } /* only continue if there are strips to evaluate */ if (estrips.first == NULL) @@ -1114,12 +1123,17 @@ void BKE_animsys_evaluate_animdata (ID *id, AnimData *adt, float ctime, short re /* evaluate NLA data */ if ((adt->nla_tracks.first) && !(adt->flag & ADT_NLA_EVAL_OFF)) { + /* evaluate NLA-stack */ animsys_evaluate_nla(&id_ptr, adt, ctime); + + /* evaluate 'active' Action (may be tweaking track) on top of results of NLA-evaluation + * - only do this if we're not exclusively evaluating the 'solo' NLA-track + */ + if ((adt->action) && !(adt->flag & ADT_NLA_SOLO_TRACK)) + animsys_evaluate_action(&id_ptr, adt->action, adt->remap, ctime); } - - /* evaluate Action data */ - // FIXME: what if the solo track was not tweaking one, then nla-solo should be checked too? - if (adt->action) + /* evaluate Active Action only */ + else if (adt->action) animsys_evaluate_action(&id_ptr, adt->action, adt->remap, ctime); /* reset tag */ diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 84f98096364..d3a01b6d610 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -359,6 +359,38 @@ NlaTrack *BKE_nlatrack_find_active (ListBase *tracks) return NULL; } +/* Toggle the 'solo' setting for the given NLA-track, making sure that it is the only one + * that has this status in its AnimData block. + */ +void BKE_nlatrack_solo_toggle (AnimData *adt, NlaTrack *nlt) +{ + NlaTrack *nt; + + /* sanity check */ + if ELEM(NULL, adt, adt->nla_tracks.first) + return; + + /* firstly, make sure 'solo' flag for all tracks is disabled */ + for (nt= adt->nla_tracks.first; nt; nt= nt->next) { + if (nt != nlt) + nt->flag &= ~NLATRACK_SOLO; + } + + /* now, enable 'solo' for the given track if appropriate */ + if (nlt) { + /* toggle solo status */ + nlt->flag ^= NLATRACK_SOLO; + + /* set or clear solo-status on AnimData */ + if (nlt->flag & NLATRACK_SOLO) + adt->flag |= ADT_NLA_SOLO_TRACK; + else + adt->flag &= ~ADT_NLA_SOLO_TRACK; + } + else + adt->flag &= ~ADT_NLA_SOLO_TRACK; +} + /* Make the given NLA-track the active one for the given stack. If no track is provided, * this function can be used to simply deactivate all the NLA tracks in the given stack too. */ diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c index 8db85ffa0b1..ed401c3596b 100644 --- a/source/blender/editors/space_nla/nla_channels.c +++ b/source/blender/editors/space_nla/nla_channels.c @@ -326,6 +326,19 @@ static void mouse_nla_channels (bAnimContext *ac, float x, int channel_index, sh case ANIMTYPE_NLATRACK: { NlaTrack *nlt= (NlaTrack *)ale->data; + AnimData *adt= BKE_animdata_from_id(ale->id); + short offset; + + /* offset for start of channel (on LHS of channel-list) */ + if (ale->id) { + /* special exception for materials */ + if (GS(ale->id->name) == ID_MA) + offset= 21 + NLACHANNEL_BUTTON_WIDTH; + else + offset= 14; + } + else + offset= 0; if (x >= (NLACHANNEL_NAMEWIDTH-NLACHANNEL_BUTTON_WIDTH)) { /* toggle protection (only if there's a toggle there) */ @@ -335,6 +348,10 @@ static void mouse_nla_channels (bAnimContext *ac, float x, int channel_index, sh /* toggle mute */ nlt->flag ^= NLATRACK_MUTED; } + else if (x <= ((NLACHANNEL_BUTTON_WIDTH*2)+offset)) { + /* toggle 'solo' */ + BKE_nlatrack_solo_toggle(adt, nlt); + } else { /* set selection */ if (selectmode == SELECT_INVERT) { @@ -359,7 +376,7 @@ static void mouse_nla_channels (bAnimContext *ac, float x, int channel_index, sh /* for now, only do something if user clicks on the 'push-down' button */ if (x >= (NLACHANNEL_NAMEWIDTH-NLACHANNEL_BUTTON_WIDTH)) { - /* activate push-down operator */ + /* activate push-down function */ // TODO: make this use the operator instead of calling the function directly // however, calling the operator requires that we supply the args, and that works with proper buttons only BKE_nla_action_pushdown(adt); diff --git a/source/blender/editors/space_nla/nla_intern.h b/source/blender/editors/space_nla/nla_intern.h index a7188a7cccd..3d8cb7548c0 100644 --- a/source/blender/editors/space_nla/nla_intern.h +++ b/source/blender/editors/space_nla/nla_intern.h @@ -30,6 +30,9 @@ /* internal exports only */ +/* **************************************** */ +/* Macros, etc. only used by NLA */ + /* -------------- NLA Channel Defines -------------- */ /* NLA channel heights */ diff --git a/source/blender/editors/space_nla/nla_select.c b/source/blender/editors/space_nla/nla_select.c index 2e3d5572711..463479c0909 100644 --- a/source/blender/editors/space_nla/nla_select.c +++ b/source/blender/editors/space_nla/nla_select.c @@ -199,7 +199,7 @@ void NLAEDIT_OT_select_all_toggle (wmOperatorType *ot) /* api callbacks */ ot->exec= nlaedit_deselectall_exec; - ot->poll= ED_operator_areaactive; + ot->poll= nlaop_poll_tweakmode_off; /* flags */ ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/; @@ -441,7 +441,7 @@ void NLAEDIT_OT_click_select (wmOperatorType *ot) /* api callbacks - absolutely no exec() this yet... */ ot->invoke= nlaedit_clickselect_invoke; - ot->poll= ED_operator_areaactive; + ot->poll= nlaop_poll_tweakmode_off; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; From 4e1bb5a806d65982320f89216b24ac7267f64f4a Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sat, 6 Jun 2009 04:44:18 +0000 Subject: [PATCH 021/114] NLA SoC: Action-line is now drawn with green colouring when a strip is being tweaked to show the relationship between them. --- source/blender/editors/space_nla/nla_draw.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index 6c4c64ea272..4fa27f4bc11 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -295,14 +295,23 @@ void draw_nla_main_data (bAnimContext *ac, SpaceNla *snla, ARegion *ar) case ANIMTYPE_NLAACTION: { + AnimData *adt= BKE_animdata_from_id(ale->id); + /* just draw a semi-shaded rect spanning the width of the viewable area if there's data */ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); - if (ale->data) - glColor4f(0.8f, 0.2f, 0.0f, 0.4f); // reddish color - hardcoded for now - else - glColor4f(0.6f, 0.5f, 0.5f, 0.3f); // greyish-red color - hardcoded for now + // TODO: if tweaking some action, use the same color as for the tweaked track (quick hack done for now) + if (adt && (adt->flag & ADT_NLA_EDIT_ON)) { + // greenish color (same as tweaking strip) - hardcoded for now + glColor4f(0.3f, 0.95f, 0.1f, 0.3f); // FIXME: only draw the actual range of the action darker? + } + else { + if (ale->data) + glColor4f(0.8f, 0.2f, 0.0f, 0.4f); // reddish color - hardcoded for now + else + glColor4f(0.6f, 0.5f, 0.5f, 0.3f); // greyish-red color - hardcoded for now + } /* draw slightly shifted up for greater separation from standard channels, * but also slightly shorter for some more contrast when viewing the strips From 9621d626a0484d19e2c18e57cbdd5f9c24c827f4 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sat, 6 Jun 2009 05:06:46 +0000 Subject: [PATCH 022/114] NLA SoC: Various user-counts and file IO bugfixes for tweaking actions... --- source/blender/blenkernel/intern/anim_sys.c | 2 +- source/blender/blenkernel/intern/nla.c | 5 ++++- source/blender/blenloader/intern/readfile.c | 2 ++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index fb4c2663c3c..390efc5ced4 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -154,7 +154,7 @@ AnimData *BKE_copy_animdata (AnimData *adt) // XXX review this... it might not be optimal behaviour yet... //id_us_plus((ID *)dadt->action); dadt->action= copy_action(adt->action); - dadt->tmpact= copy_action(adt->action); + dadt->tmpact= copy_action(adt->tmpact); /* duplicate NLA data */ copy_nladata(&dadt->nla_tracks, &adt->nla_tracks); diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index d3a01b6d610..9acbad32a42 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -675,11 +675,12 @@ short BKE_nla_tweakmode_enter (AnimData *adt) /* handle AnimData level changes: * - 'real' active action to temp storage (no need to change user-counts) - * - action of active strip set to be the 'active action' + * - action of active strip set to be the 'active action', and have its usercount incremented * - editing-flag for this AnimData block should also get turned on (for more efficient restoring) */ adt->tmpact= adt->action; adt->action= activeStrip->act; + id_us_plus(&activeStrip->act->id); adt->flag |= ADT_NLA_EDIT_ON; /* done! */ @@ -706,10 +707,12 @@ void BKE_nla_tweakmode_exit (AnimData *adt) nlt->flag &= ~NLATRACK_DISABLED; /* handle AnimData level changes: + * - 'temporary' active action needs its usercount decreased, since we're removing this reference * - 'real' active action is restored from storage * - storage pointer gets cleared (to avoid having bad notes hanging around) * - editing-flag for this AnimData block should also get turned off */ + if (adt->action) adt->action->id.us--; adt->action= adt->tmpact; adt->tmpact= NULL; adt->flag &= ~ADT_NLA_EDIT_ON; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index e3869d4bc8a..c306f5bcde4 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -1896,6 +1896,7 @@ static void lib_link_animdata(FileData *fd, ID *id, AnimData *adt) /* link action data */ adt->action= newlibadr_us(fd, id->lib, adt->action); + adt->tmpact= newlibadr_us(fd, id->lib, adt->tmpact); /* link drivers */ lib_link_fcurves(fd, id, &adt->drivers); @@ -9406,6 +9407,7 @@ static void expand_animdata(FileData *fd, Main *mainvar, AnimData *adt) /* own action */ expand_doit(fd, mainvar, adt->action); + expand_doit(fd, mainvar, adt->tmpact); /* drivers - assume that these F-Curves have driver data to be in this list... */ for (fcd= adt->drivers.first; fcd; fcd= fcd->next) { From 34f29749c8d83b279dc0dd186da32018d0b30685 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sun, 7 Jun 2009 06:49:04 +0000 Subject: [PATCH 023/114] NLA SoC: RNA wrapping for NLA Data Most of the relevant properties have been wrapped. - There are still some properties I'm not sure about whether they should be exposed at all (which have been left out for now). Most of these are really internal flags which are used in a few select places. - To maintain the integrity of the settings, I've included some custom code for a few of the setters (i.e. scale/end-frame) where changing one should result in a change in the other and vica-versa. Also, tweaked the wrapping for a few other types. Another side effect of this commit is that I can now uncommented some code for using F-Curves to control the influence and time of the strips. These F-Curves would need to be specifically attached to the NLA-Strip they affect for now (TODO: I need to review this again...), and as such, cannot be used yet since there's no (end-user-accessible) way to do this :) --- source/blender/blenkernel/intern/anim_sys.c | 5 +- source/blender/makesrna/RNA_access.h | 2 + source/blender/makesrna/intern/makesrna.c | 1 + .../blender/makesrna/intern/rna_animation.c | 2 +- source/blender/makesrna/intern/rna_internal.h | 1 + source/blender/makesrna/intern/rna_nla.c | 329 ++++++++++++++++++ 6 files changed, 335 insertions(+), 5 deletions(-) create mode 100644 source/blender/makesrna/intern/rna_nla.c diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 390efc5ced4..44817b47860 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -657,16 +657,13 @@ void nlastrip_evaluate_controls (NlaStrip *strip, float ctime) /* now strip's evaluate F-Curves for these settings (if applicable) */ if (strip->fcurves.first) { -#if 0 PointerRNA strip_ptr; - FCurve *fcu; /* create RNA-pointer needed to set values */ RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr); /* execute these settings as per normal */ - animsys_evaluate_fcurves(&actstrip_ptr, &strip->fcurves, NULL, ctime); -#endif + animsys_evaluate_fcurves(&strip_ptr, &strip->fcurves, NULL, ctime); } } diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index eb355a34f9f..ad9869f853e 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -189,6 +189,8 @@ extern StructRNA RNA_MultiresModifier; extern StructRNA RNA_MusgraveTexture; extern StructRNA RNA_NandController; extern StructRNA RNA_NearSensor; +extern StructRNA RNA_NlaTrack; +extern StructRNA RNA_NlaStrip; extern StructRNA RNA_Node; extern StructRNA RNA_NodeTree; extern StructRNA RNA_NoiseTexture; diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index 1cfba4286c7..15140e4f744 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -1794,6 +1794,7 @@ RNAProcessItem PROCESS_ITEMS[]= { {"rna_mesh.c", RNA_def_mesh}, {"rna_meta.c", RNA_def_meta}, {"rna_modifier.c", RNA_def_modifier}, + {"rna_nla.c", RNA_def_nla}, {"rna_nodetree.c", RNA_def_nodetree}, {"rna_object.c", RNA_def_object}, {"rna_object_force.c", RNA_def_object_force}, diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c index 702dc9fa65d..3da8eb33bfd 100644 --- a/source/blender/makesrna/intern/rna_animation.c +++ b/source/blender/makesrna/intern/rna_animation.c @@ -184,7 +184,7 @@ void rna_def_animdata(BlenderRNA *brna) /* NLA */ prop= RNA_def_property(srna, "nla_tracks", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "nla_tracks", NULL); - RNA_def_property_struct_type(prop, "UnknownType"); // XXX! + RNA_def_property_struct_type(prop, "NlaTrack"); RNA_def_property_ui_text(prop, "NLA Tracks", "NLA Tracks (i.e. Animation Layers)."); /* Action */ diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h index 9071efe71f7..16f7a11d1be 100644 --- a/source/blender/makesrna/intern/rna_internal.h +++ b/source/blender/makesrna/intern/rna_internal.h @@ -139,6 +139,7 @@ void RNA_def_material(struct BlenderRNA *brna); void RNA_def_mesh(struct BlenderRNA *brna); void RNA_def_meta(struct BlenderRNA *brna); void RNA_def_modifier(struct BlenderRNA *brna); +void RNA_def_nla(struct BlenderRNA *brna); void RNA_def_nodetree(struct BlenderRNA *brna); void RNA_def_object(struct BlenderRNA *brna); void RNA_def_object_force(struct BlenderRNA *brna); diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c new file mode 100644 index 00000000000..35d1e415243 --- /dev/null +++ b/source/blender/makesrna/intern/rna_nla.c @@ -0,0 +1,329 @@ +/** + * $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. + * + * Contributor(s): Blender Foundation (2009), Joshua Leung + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include + +#include "RNA_define.h" +#include "RNA_types.h" + +#include "rna_internal.h" + +#include "DNA_anim_types.h" +#include "DNA_action_types.h" +#include "DNA_scene_types.h" + +#include "MEM_guardedalloc.h" + +#ifdef RNA_RUNTIME + +#include +#include + +static void rna_NlaStrip_start_frame_set(PointerRNA *ptr, float value) +{ + NlaStrip *data= (NlaStrip*)ptr->data; + CLAMP(value, 1, data->end); + data->start= value; +} + +static void rna_NlaStrip_end_frame_set(PointerRNA *ptr, float value) +{ + NlaStrip *data= (NlaStrip*)ptr->data; + float len, actlen; + + /* clamp value to lie within valid limits - must not have zero or negative length strip */ + CLAMP(value, data->start+0.1f, MAXFRAME); + data->end= value; + + /* calculate the lengths the strip and its action (if applicable) */ + len= data->end - data->start; + actlen= data->actend - data->actstart; + if (IS_EQ(actlen, 0.0f)) actlen= 1.0f; + + /* now, adjust the 'scale' setting to reflect this (so that this change can be valid) */ + data->scale= len / ((actlen) * data->repeat); +} + +static void rna_NlaStrip_scale_set(PointerRNA *ptr, float value) +{ + NlaStrip *data= (NlaStrip*)ptr->data; + float actlen, mapping; + + /* set scale value */ + CLAMP(value, 0.0001f, 1000.0f); /* NOTE: these need to be synced with the values in the property definition in rna_def_nlastrip() */ + data->scale= value; + + /* calculate existing factors */ + actlen= data->actend - data->actstart; + if (IS_EQ(actlen, 0.0f)) actlen= 1.0f; + mapping= data->scale * data->repeat; + + /* adjust endpoint of strip in response to this */ + if (IS_EQ(mapping, 0.0f) == 0) + data->end = (actlen * mapping) + data->start; + else + printf("NlaStrip Set Scale Error (in RNA): Scale = %0.4f, Repeat = %0.4f \n", data->scale, data->repeat); +} + +static void rna_NlaStrip_blend_in_set(PointerRNA *ptr, float value) +{ + NlaStrip *data= (NlaStrip*)ptr->data; + float len; + + /* blend-in is limited to the length of the strip, and also cannot overlap with blendout */ + len= (data->end - data->start) - data->blendout; + CLAMP(value, 0, len); + + data->blendin= value; +} + +static void rna_NlaStrip_blend_out_set(PointerRNA *ptr, float value) +{ + NlaStrip *data= (NlaStrip*)ptr->data; + float len; + + /* blend-out is limited to the length of the strip */ + len= (data->end - data->start); + CLAMP(value, 0, len); + + /* it also cannot overlap with blendin */ + if ((len - value) < data->blendin) + value= len - data->blendin; + + data->blendout= value; +} + +static void rna_NlaStrip_action_start_frame_set(PointerRNA *ptr, float value) +{ + NlaStrip *data= (NlaStrip*)ptr->data; + CLAMP(value, 1, data->actend); + data->actstart= value; +} + +static void rna_NlaStrip_action_end_frame_set(PointerRNA *ptr, float value) +{ + NlaStrip *data= (NlaStrip*)ptr->data; + CLAMP(value, data->actstart, MAXFRAME); + data->actend= value; +} + +#else + +void rna_def_nlastrip(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + /* enum defs */ + static EnumPropertyItem prop_type_items[] = { + {NLASTRIP_TYPE_CLIP, "CLIP", "Action Clip", "NLA Strip references some Action."}, + {NLASTRIP_TYPE_TRANSITION, "TRANSITION", "Transition", "NLA Strip 'transitions' between adjacent strips."}, + {0, NULL, NULL, NULL}}; + static EnumPropertyItem prop_mode_blend_items[] = { + {NLASTRIP_MODE_BLEND, "BLEND", "Blend", "Results of strip and accumulated results are combined in ratio governed by influence."}, + {NLASTRIP_MODE_ADD, "ADD", "Add", "Weighted result of strip is added to the accumlated results."}, + {NLASTRIP_MODE_SUBTRACT, "SUBTRACT", "Subtract", "Weighted result of strip is removed from the accumlated results."}, + {NLASTRIP_MODE_MULTIPLY, "MULITPLY", "Multiply", "Weighted result of strip is multiplied with the accumlated results."}, + {0, NULL, NULL, NULL}}; + static EnumPropertyItem prop_mode_extend_items[] = { + {NLASTRIP_EXTEND_NOTHING, "NOTHING", "Nothing", "Strip has no influence past its extents."}, + {NLASTRIP_EXTEND_HOLD, "HOLD", "Hold", "Hold the first frame if no previous strips in track, and always hold last frame."}, + {NLASTRIP_EXTEND_HOLD_FORWARD, "HOLD_FORWARD", "Hold Forward", "Only hold last frame."}, + {0, NULL, NULL, NULL}}; + + /* struct definition */ + srna= RNA_def_struct(brna, "NlaStrip", NULL); + RNA_def_struct_ui_text(srna, "NLA Strip", "A container referencing an existing Action."); + //RNA_def_struct_ui_icon(srna, ICON_ACTION); + + /* Enums */ + 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, "Type", "Type of NLA Strip."); + + prop= RNA_def_property(srna, "extrapolation", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "extendmode"); + RNA_def_property_enum_items(prop, prop_mode_extend_items); + RNA_def_property_ui_text(prop, "Extrapolation", "Action to take for gaps past the strip extents."); + + prop= RNA_def_property(srna, "blending", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "blendmode"); + RNA_def_property_enum_items(prop, prop_mode_blend_items); + RNA_def_property_ui_text(prop, "Blending", "Method used for combining strip's result with accumulated result."); + + /* Strip extents */ + prop= RNA_def_property(srna, "start_frame", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "start"); + RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_start_frame_set", NULL); + RNA_def_property_ui_text(prop, "Start Frame", ""); + + prop= RNA_def_property(srna, "end_frame", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "end"); + RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_end_frame_set", NULL); + RNA_def_property_ui_text(prop, "End Frame", ""); + + /* Blending */ + prop= RNA_def_property(srna, "blend_in", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "blendin"); + RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_blend_in_set", NULL); + RNA_def_property_ui_text(prop, "Blend In", "Number of frames at start of strip to fade in influence."); + + prop= RNA_def_property(srna, "blend_out", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "blendout"); + RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_blend_out_set", NULL); + RNA_def_property_ui_text(prop, "Blend Out", ""); + + prop= RNA_def_property(srna, "auto_blending", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_AUTO_BLENDS); + RNA_def_property_ui_text(prop, "Auto Blend In/Out", "Number of frames for Blending In/Out is automatically determined from overlapping strips."); + + /* Action */ + prop= RNA_def_property(srna, "action", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "act"); + RNA_def_property_ui_text(prop, "Action", "Action referenced by this strip."); + + /* Action extents */ + prop= RNA_def_property(srna, "action_start_frame", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "actstart"); + RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_action_start_frame_set", NULL); + RNA_def_property_ui_text(prop, "Action Start Frame", ""); + + prop= RNA_def_property(srna, "action_end_frame", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "actend"); + RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_action_end_frame_set", NULL); + RNA_def_property_ui_text(prop, "Action End Frame", ""); + + /* Action Reuse */ + prop= RNA_def_property(srna, "repeat", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "repeat"); + RNA_def_property_range(prop, 1.0f, 1000.0f); /* these limits have currently be chosen arbitarily, but could be extended (minimum should still be > 0 though) if needed... */ + RNA_def_property_ui_text(prop, "Repeat", "Number of times to repeat the "); + + prop= RNA_def_property(srna, "scale", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "scale"); + RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_scale_set", NULL); + RNA_def_property_range(prop, 0.0001f, 1000.0f); /* these limits can be extended, but beyond this, we can get some crazy+annoying bugs due to numeric errors */ + RNA_def_property_ui_text(prop, "Scale", "Scaling factor for action."); + + // TODO: strip's F-Curves? + + /* Strip's F-Modifiers */ + prop= RNA_def_property(srna, "modifiers", PROP_COLLECTION, PROP_NONE); + RNA_def_property_struct_type(prop, "FModifier"); + RNA_def_property_ui_text(prop, "Modifiers", "Modifiers affecting all the F-Curves in the referenced Action."); + + /* Settings - Values necessary for evaluation */ + prop= RNA_def_property(srna, "influence", PROP_FLOAT, PROP_NONE); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "Influence", "Amount the strip contributes to the current result."); + + prop= RNA_def_property(srna, "strip_time", PROP_FLOAT, PROP_NONE); + RNA_def_property_ui_text(prop, "Strip Time", "Frame of referenced Action to evaluate."); + + prop= RNA_def_property(srna, "animated_influence", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); // XXX for now, not editable + RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_USR_INFLUENCE); + RNA_def_property_ui_text(prop, "Animated Influence", "Influence setting is controlled by an F-Curve rather than automatically determined."); + + prop= RNA_def_property(srna, "animated_time", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); // XXX for now, not editable + RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_USR_INFLUENCE); + RNA_def_property_ui_text(prop, "Animated Strip Time", "Strip time is controlled by an F-Curve rather than automatically determined."); + + /* settings */ + prop= RNA_def_property(srna, "active", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* can be made editable by hooking it up to the necessary NLA API methods */ + RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_ACTIVE); + RNA_def_property_ui_text(prop, "Active", "NLA Strip is active."); + + prop= RNA_def_property(srna, "selected", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_SELECT); + RNA_def_property_ui_text(prop, "Selected", "NLA Strip is selected."); + + prop= RNA_def_property(srna, "muted", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_MUTED); + RNA_def_property_ui_text(prop, "Muted", "NLA Strip is not evaluated."); + + prop= RNA_def_property(srna, "reversed", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_REVERSE); + RNA_def_property_ui_text(prop, "Reversed", "NLA Strip is played back in reverse order (only when timing is automatically determined)."); + + // TODO: + // - sync length +} + +void rna_def_nlatrack(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna= RNA_def_struct(brna, "NlaTrack", NULL); + RNA_def_struct_ui_text(srna, "NLA Track", "A animation layer containing Actions referenced as NLA strips."); + //RNA_def_struct_ui_icon(srna, ICON_ACTION); + + /* strips collection */ + prop= RNA_def_property(srna, "strips", PROP_COLLECTION, PROP_NONE); + RNA_def_property_struct_type(prop, "NlaStrip"); + RNA_def_property_ui_text(prop, "NLA Strips", "NLA Strips on this NLA-track."); + + /* name property */ + prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); + RNA_def_property_ui_text(prop, "Name", ""); + RNA_def_struct_name_property(srna, prop); + + /* settings */ + prop= RNA_def_property(srna, "active", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* can be made editable by hooking it up to the necessary NLA API methods */ + RNA_def_property_boolean_sdna(prop, NULL, "flag", NLATRACK_ACTIVE); + RNA_def_property_ui_text(prop, "Active", "NLA Track is active."); + + prop= RNA_def_property(srna, "solo", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* can be made editable by hooking it up to the necessary NLA API methods */ + RNA_def_property_boolean_sdna(prop, NULL, "flag", NLATRACK_SOLO); + RNA_def_property_ui_text(prop, "Solo", "NLA Track is evaluated itself (i.e. active Action and all other NLA Tracks in the same AnimData block are disabled)."); + + prop= RNA_def_property(srna, "selected", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", NLATRACK_SELECTED); + RNA_def_property_ui_text(prop, "Selected", "NLA Track is selected."); + + prop= RNA_def_property(srna, "muted", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", NLATRACK_MUTED); + RNA_def_property_ui_text(prop, "Muted", "NLA Track is not evaluated."); + + prop= RNA_def_property(srna, "locked", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", NLATRACK_PROTECTED); + RNA_def_property_ui_text(prop, "Locked", "NLA Track is locked."); +} + +/* --------- */ + +void RNA_def_nla(BlenderRNA *brna) +{ + rna_def_nlatrack(brna); + rna_def_nlastrip(brna); +} + + +#endif From 43c7c15e2be555454f54840307fd5ea7d61d0216 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sun, 7 Jun 2009 07:04:31 +0000 Subject: [PATCH 024/114] NLA SoC: 2 little tweaks - Evaluation times for strips are now strictly clamped to the endpoints of the strips - i.e. if a strip has 'extend' on, the strip's evaluation time won't continue to change as time changes - New NLA Editor instances now have auto-snapping turned on by default (as they should) --- source/blender/blenkernel/intern/anim_sys.c | 10 ++++++++++ source/blender/editors/space_nla/space_nla.c | 3 +++ 2 files changed, 13 insertions(+) diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 44817b47860..3290e06dfb4 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -730,6 +730,16 @@ static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index */ if ((estrip == NULL) || (estrip->flag & NLASTRIP_FLAG_MUTED)) return; + + /* if ctime was not within the boundaries of the strip, clamp! */ + switch (side) { + case NES_TIME_BEFORE: /* extend first frame only */ + ctime= estrip->start; + break; + case NES_TIME_AFTER: /* extend last frame only */ + ctime= estrip->end; + break; + } /* evaluate strip's evaluation controls * - skip if no influence (i.e. same effect as muting the strip) diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c index 39579ec96da..32ced127831 100644 --- a/source/blender/editors/space_nla/space_nla.c +++ b/source/blender/editors/space_nla/space_nla.c @@ -79,6 +79,9 @@ static SpaceLink *nla_new(const bContext *C) /* allocate DopeSheet data for NLA Editor */ snla->ads= MEM_callocN(sizeof(bDopeSheet), "NlaEdit DopeSheet"); + /* set auto-snapping settings */ + snla->autosnap = SACTSNAP_FRAME; + /* header */ ar= MEM_callocN(sizeof(ARegion), "header for nla"); From 019baf8b8fc0cae24b8706a557a296e598290615 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sun, 7 Jun 2009 11:37:15 +0000 Subject: [PATCH 025/114] NLA SoC: Adding skeleton code for a buttons region in NLA If anyone's doing any testing at this point, please check if this works ok for files with new/old NLA Editors, as I was having some problems with one of my testing (saved from this branch) files with this. --- .../blender/editors/space_nla/nla_buttons.c | 198 ++++++++++++++++++ source/blender/editors/space_nla/nla_intern.h | 7 + source/blender/editors/space_nla/nla_ops.c | 7 + source/blender/editors/space_nla/space_nla.c | 104 +++++++++ 4 files changed, 316 insertions(+) create mode 100644 source/blender/editors/space_nla/nla_buttons.c diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c new file mode 100644 index 00000000000..118dc988dfb --- /dev/null +++ b/source/blender/editors/space_nla/nla_buttons.c @@ -0,0 +1,198 @@ +/** + * $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, Joshua Leung + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include +#include +#include +#include + +#include "DNA_anim_types.h" +#include "DNA_action_types.h" +#include "DNA_object_types.h" +#include "DNA_space_types.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" +#include "DNA_userdef_types.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_arithb.h" +#include "BLI_blenlib.h" +#include "BLI_editVert.h" +#include "BLI_rand.h" + +#include "BKE_animsys.h" +#include "BKE_nla.h" +#include "BKE_action.h" +#include "BKE_context.h" +#include "BKE_curve.h" +#include "BKE_customdata.h" +#include "BKE_depsgraph.h" +#include "BKE_fcurve.h" +#include "BKE_object.h" +#include "BKE_global.h" +#include "BKE_scene.h" +#include "BKE_screen.h" +#include "BKE_utildefines.h" + +#include "BIF_gl.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "ED_anim_api.h" +#include "ED_keyframing.h" +#include "ED_screen.h" +#include "ED_types.h" +#include "ED_util.h" + +#include "UI_interface.h" +#include "UI_resources.h" +#include "UI_view2d.h" + +#include "nla_intern.h" // own include + + +/* ******************* nla editor space & buttons ************** */ + +#define B_NOP 1 +#define B_REDR 2 + +/* -------------- */ + +static void do_nla_region_buttons(bContext *C, void *arg, int event) +{ + //Scene *scene= CTX_data_scene(C); + + switch(event) { + + } + + /* default for now */ + //WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob); +} + +static int nla_panel_context(const bContext *C, bAnimListElem **ale, NlaTrack **nlt) +{ + bAnimContext ac; + bAnimListElem *elem= NULL; + + /* for now, only draw if we could init the anim-context info (necessary for all animation-related tools) + * to work correctly is able to be correctly retrieved. There's no point showing empty panels? + */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return 0; + + // XXX + return 1; + + /* try to find 'active' F-Curve */ + //elem= get_active_fcurve_channel(&ac); + if(elem == NULL) + return 0; + + if(nlt) + *nlt= (NlaTrack*)elem->data; + if(ale) + *ale= elem; + else + MEM_freeN(elem); + + return 1; +} + +static int nla_panel_poll(const bContext *C, PanelType *pt) +{ + return nla_panel_context(C, NULL, NULL); +} + +static void nla_panel_properties(const bContext *C, Panel *pa) +{ + bAnimListElem *ale; + NlaTrack *nlt; + uiBlock *block; + char name[128]; + + if(!nla_panel_context(C, &ale, &nlt)) + return; + + block= uiLayoutFreeBlock(pa->layout); + uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL); + + /* Info - Active F-Curve */ + uiDefBut(block, LABEL, 1, "Active NLA Strip:", 10, 200, 150, 19, NULL, 0.0, 0.0, 0, 0, ""); + + + //MEM_freeN(ale); +} + + +/* ******************* general ******************************** */ + + +void nla_buttons_register(ARegionType *art) +{ + PanelType *pt; + + pt= MEM_callocN(sizeof(PanelType), "spacetype nla panel properties"); + strcpy(pt->idname, "NLA_PT_properties"); + strcpy(pt->label, "Properties"); + pt->draw= nla_panel_properties; + pt->poll= nla_panel_poll; + BLI_addtail(&art->paneltypes, pt); +} + +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); + } + return OPERATOR_FINISHED; +} + +void NLAEDIT_OT_properties(wmOperatorType *ot) +{ + ot->name= "Properties"; + ot->idname= "NLAEDIT_OT_properties"; + + ot->exec= nla_properties; + ot->poll= ED_operator_nla_active; + + /* flags */ + ot->flag= 0; +} diff --git a/source/blender/editors/space_nla/nla_intern.h b/source/blender/editors/space_nla/nla_intern.h index 3d8cb7548c0..00de0498e4b 100644 --- a/source/blender/editors/space_nla/nla_intern.h +++ b/source/blender/editors/space_nla/nla_intern.h @@ -48,6 +48,13 @@ /* channel toggle-buttons */ #define NLACHANNEL_BUTTON_WIDTH 16 +/* **************************************** */ +/* space_nla.c / nla_buttons.c */ + +ARegion *nla_has_buttons_region(ScrArea *sa); + +void nla_buttons_register(ARegionType *art); +void NLAEDIT_OT_properties(wmOperatorType *ot); /* **************************************** */ /* nla_draw.c */ diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c index 057e4b05656..f59cbd9c1d4 100644 --- a/source/blender/editors/space_nla/nla_ops.c +++ b/source/blender/editors/space_nla/nla_ops.c @@ -115,6 +115,9 @@ int nlaop_poll_tweakmode_on (bContext *C) void nla_operatortypes(void) { + /* view */ + WM_operatortype_append(NLAEDIT_OT_properties); + /* channels */ WM_operatortype_append(NLA_OT_channels_click); WM_operatortype_append(NLA_OT_channels_select_border); @@ -197,6 +200,10 @@ void nla_keymap(wmWindowManager *wm) { ListBase *keymap; + /* keymap for all regions */ + keymap= WM_keymap_listbase(wm, "NLA Generic", SPACE_NLA, 0); + WM_keymap_add_item(keymap, "NLAEDIT_OT_properties", NKEY, KM_PRESS, 0, 0); + /* channels */ /* Channels are not directly handled by the NLA Editor module, but are inherited from the Animation module. * Most of the relevant operations, keymaps, drawing, etc. can therefore all be found in that module instead, as there diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c index 32ced127831..5490f40eb03 100644 --- a/source/blender/editors/space_nla/space_nla.c +++ b/source/blender/editors/space_nla/space_nla.c @@ -66,6 +66,39 @@ #include "nla_intern.h" // own include +/* ******************** manage regions ********************* */ + +ARegion *nla_has_buttons_region(ScrArea *sa) +{ + ARegion *ar, *arnew; + + for (ar= sa->regionbase.first; ar; ar= ar->next) { + if (ar->regiontype==RGN_TYPE_UI) + return ar; + } + + /* add subdiv level; after main */ + for (ar= sa->regionbase.first; ar; ar= ar->next) { + if (ar->regiontype==RGN_TYPE_WINDOW) + break; + } + + /* is error! */ + if (ar==NULL) return NULL; + + arnew= MEM_callocN(sizeof(ARegion), "buttons for nla"); + + BLI_insertlinkafter(&sa->regionbase, ar, arnew); + arnew->regiontype= RGN_TYPE_UI; + arnew->alignment= RGN_ALIGN_RIGHT; + + arnew->flag = RGN_FLAG_HIDDEN; + + return arnew; +} + + + /* ******************** default callbacks for nla space ***************** */ static SpaceLink *nla_new(const bContext *C) @@ -130,6 +163,14 @@ static SpaceLink *nla_new(const bContext *C) ar->v2d.align= V2D_ALIGN_NO_NEG_Y; ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL; + /* ui buttons */ + ar= MEM_callocN(sizeof(ARegion), "buttons area for nla"); + + BLI_addtail(&snla->regionbase, ar); + ar->regiontype= RGN_TYPE_UI; + ar->alignment= RGN_ALIGN_RIGHT; + ar->flag = RGN_FLAG_HIDDEN; + return (SpaceLink *)snla; } @@ -178,6 +219,8 @@ static void nla_channel_area_init(wmWindowManager *wm, ARegion *ar) // TODO: cannot use generic copy, need special NLA version keymap= WM_keymap_listbase(wm, "NLA Channels", SPACE_NLA, 0); /* XXX weak? */ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); + keymap= WM_keymap_listbase(wm, "NLA Generic", SPACE_NLA, 0); + WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); } /* draw entirely, view changes should be handled here */ @@ -221,6 +264,8 @@ static void nla_main_area_init(wmWindowManager *wm, ARegion *ar) /* own keymap */ keymap= WM_keymap_listbase(wm, "NLA Data", SPACE_NLA, 0); /* XXX weak? */ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); + keymap= WM_keymap_listbase(wm, "NLA Generic", SPACE_NLA, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); } static void nla_main_area_draw(const bContext *C, ARegion *ar) @@ -309,6 +354,52 @@ static void nla_header_area_draw(const bContext *C, ARegion *ar) UI_view2d_view_restore(C); } +/* add handlers, stuff you only do once or on area/region changes */ +static void nla_buttons_area_init(wmWindowManager *wm, ARegion *ar) +{ + ListBase *keymap; + + ED_region_panels_init(wm, ar); + + keymap= WM_keymap_listbase(wm, "NLA Generic", SPACE_NLA, 0); + WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); +} + +static void nla_buttons_area_draw(const bContext *C, ARegion *ar) +{ + ED_region_panels(C, ar, 1, NULL); +} + +static void nla_region_listener(ARegion *ar, wmNotifier *wmn) +{ + /* context changes */ + switch(wmn->category) { + case NC_SCENE: + switch(wmn->data) { + case ND_OB_ACTIVE: + case ND_FRAME: + case ND_MARKERS: + ED_region_tag_redraw(ar); + break; + } + break; + case NC_OBJECT: + switch(wmn->data) { + case ND_BONE_ACTIVE: + case ND_BONE_SELECT: + case ND_KEYS: + ED_region_tag_redraw(ar); + break; + } + break; + default: + if(wmn->data==ND_KEYS) + ED_region_tag_redraw(ar); + + } +} + + static void nla_main_area_listener(ARegion *ar, wmNotifier *wmn) { /* context changes */ @@ -439,6 +530,19 @@ void ED_spacetype_nla(void) BLI_addhead(&st->regiontypes, art); + /* regions: UI buttons */ + art= MEM_callocN(sizeof(ARegionType), "spacetype nla region"); + art->regionid = RGN_TYPE_UI; + art->minsizex= 200; + art->keymapflag= ED_KEYMAP_UI; + art->listener= nla_region_listener; + art->init= nla_buttons_area_init; + art->draw= nla_buttons_area_draw; + + BLI_addhead(&st->regiontypes, art); + + nla_buttons_register(art); + BKE_spacetype_register(st); } From 39ff455eecdacb6cc7cfcc1003b9faf6e6b8c21b Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Mon, 8 Jun 2009 01:07:19 +0000 Subject: [PATCH 026/114] NLA SoC: Added button for entering/exiting TweakMode - Should the icons used for this be reversed? --- source/blender/editors/space_nla/nla_edit.c | 4 ++++ source/blender/editors/space_nla/nla_header.c | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index f7053957667..49d43f29c5f 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -120,6 +120,10 @@ static int nlaedit_enable_tweakmode_exec (bContext *C, wmOperator *op) ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); WM_event_add_notifier(C, NC_SCENE, NULL); } + else { + BKE_report(op->reports, RPT_ERROR, "No active strip(s) to enter tweakmode on."); + return OPERATOR_CANCELLED; + } /* done */ return OPERATOR_FINISHED; diff --git a/source/blender/editors/space_nla/nla_header.c b/source/blender/editors/space_nla/nla_header.c index 0dcd3198db0..7ce7536878b 100644 --- a/source/blender/editors/space_nla/nla_header.c +++ b/source/blender/editors/space_nla/nla_header.c @@ -118,6 +118,7 @@ static void do_nla_buttons(bContext *C, void *arg, int event) void nla_header_buttons(const bContext *C, ARegion *ar) { SpaceNla *snla= (SpaceNla *)CTX_wm_space_data(C); + Scene *scene= CTX_data_scene(C); ScrArea *sa= CTX_wm_area(C); uiBlock *block; int xco, yco= 3; @@ -178,6 +179,14 @@ void nla_header_buttons(const bContext *C, ARegion *ar) } xco += 98; + /* Tweakmode... */ + // XXX these icons need to be changed + if (scene->flag & SCE_NLA_EDIT_ON) + uiDefIconTextButO(block, BUT, "NLAEDIT_OT_tweakmode_exit", WM_OP_INVOKE_REGION_WIN, ICON_NLA, "Exit TweakMode", xco,yco,130,YIC, "Restore the true active action. (TAB)"); + else + uiDefIconTextButO(block, BUT, "NLAEDIT_OT_tweakmode_enter", WM_OP_INVOKE_REGION_WIN, ICON_EDIT, "Enter TweakMode", xco,yco,130,YIC, "Temporarily set the action referenced by the active strip as the active action so that it can be tweaked. (TAB)"); + xco+= 150; + /* always as last */ UI_view2d_totRect_set(&ar->v2d, xco+XIC+80, ar->v2d.tot.ymax-ar->v2d.tot.ymin); From a8f81615183dea449d337b24338e60bf928b3653 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Mon, 8 Jun 2009 11:11:39 +0000 Subject: [PATCH 027/114] NLA SoC: Fixed Outliner drawing for NLA data, and set icons for RNA wrapping of this data... --- source/blender/editors/space_outliner/outliner.c | 14 ++++++++------ .../editors/space_outliner/outliner_intern.h | 1 + source/blender/makesrna/intern/rna_nla.c | 4 ++-- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/source/blender/editors/space_outliner/outliner.c b/source/blender/editors/space_outliner/outliner.c index 16748af39d5..eba0aa84e85 100644 --- a/source/blender/editors/space_outliner/outliner.c +++ b/source/blender/editors/space_outliner/outliner.c @@ -949,7 +949,6 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i /* NLA Data */ if (adt->nla_tracks.first) { -#if 0 TreeElement *tenla= outliner_add_element(soops, &te->subtree, adt, te, TSE_NLA, 0); NlaTrack *nlt; int a= 0; @@ -957,17 +956,18 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i tenla->name= "NLA Tracks"; for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) { - TreeElement *tenlt= outliner_add_element(soops, &te->subtree, nlt, te, TSE_NLA_TRACK, a); - bActionStrip *strip; + TreeElement *tenlt= outliner_add_element(soops, &tenla->subtree, nlt, tenla, TSE_NLA_TRACK, a); + NlaStrip *strip; TreeElement *ten; int b= 0; - for (strip=nlt->strips.first; strip; strip=strip->next, a++) { - ten= outliner_add_element(soops, &tenla->subtree, strip->act, tenla, TSE_NLA_ACTION, a); + tenlt->name= nlt->name; + + for (strip=nlt->strips.first; strip; strip=strip->next, b++) { + ten= outliner_add_element(soops, &tenlt->subtree, strip->act, tenlt, TSE_NLA_ACTION, b); if(ten) ten->directdata= strip; } } -#endif } } else if(type==TSE_SEQUENCE) { @@ -3521,6 +3521,8 @@ static void tselem_draw_icon(float x, float y, TreeStoreElem *tselem, TreeElemen UI_icon_draw(x, y, ICON_ANIM_DATA); break; // xxx case TSE_NLA: UI_icon_draw(x, y, ICON_NLA); break; + case TSE_NLA_TRACK: + UI_icon_draw(x, y, ICON_NLA); break; // XXX case TSE_NLA_ACTION: UI_icon_draw(x, y, ICON_ACTION); break; case TSE_DEFGROUP_BASE: diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h index 48c904121a5..204298f2b70 100644 --- a/source/blender/editors/space_outliner/outliner_intern.h +++ b/source/blender/editors/space_outliner/outliner_intern.h @@ -94,6 +94,7 @@ typedef struct TreeElement { #define TSE_RNA_STRUCT 30 #define TSE_RNA_PROPERTY 31 #define TSE_RNA_ARRAY_ELEM 32 +#define TSE_NLA_TRACK 33 /* outliner search flags */ #define OL_FIND 0 diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c index 35d1e415243..0a7d17adc09 100644 --- a/source/blender/makesrna/intern/rna_nla.c +++ b/source/blender/makesrna/intern/rna_nla.c @@ -155,7 +155,7 @@ void rna_def_nlastrip(BlenderRNA *brna) /* struct definition */ srna= RNA_def_struct(brna, "NlaStrip", NULL); RNA_def_struct_ui_text(srna, "NLA Strip", "A container referencing an existing Action."); - //RNA_def_struct_ui_icon(srna, ICON_ACTION); + RNA_def_struct_ui_icon(srna, ICON_NLA); // XXX /* Enums */ prop= RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); @@ -281,7 +281,7 @@ void rna_def_nlatrack(BlenderRNA *brna) srna= RNA_def_struct(brna, "NlaTrack", NULL); RNA_def_struct_ui_text(srna, "NLA Track", "A animation layer containing Actions referenced as NLA strips."); - //RNA_def_struct_ui_icon(srna, ICON_ACTION); + RNA_def_struct_ui_icon(srna, ICON_NLA); /* strips collection */ prop= RNA_def_property(srna, "strips", PROP_COLLECTION, PROP_NONE); From 4b8b9b222eebbfa01566b90a00bba8a35835c671 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 9 Jun 2009 04:39:33 +0000 Subject: [PATCH 028/114] NLA SoC: Added buttons in NKEY region for NLA Editor - Most of the settings wrapped in RNA have been exposed here using the new layout engine stuff from Brecht (C-API). I've tried to maintain a hierarchy of high-level (owner, generic-settings) to low-level (children, specialised-settings) here, which seems to be the prevailing guidelines? (It took a while to try to understand how this all fitted together, since there were no clear examples on how to use this anywhere) - NLA-Strip Modifiers have not been exposed yet. They still use the old-style drawing, which may/may not be compatible here. - Fixed a bug with how the notifiers from this panel get sent. I really don't know how the compiler would have missed the undeclared pointer that was being used ('ob'). --- .../blender/editors/animation/anim_filter.c | 1 - .../blender/editors/space_nla/nla_buttons.c | 224 +++++++++++++++--- 2 files changed, 194 insertions(+), 31 deletions(-) diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index 32405571b57..cdda13d999d 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -730,7 +730,6 @@ static int animdata_filter_nla (ListBase *anim_data, AnimData *adt, int filter_m /* only include this track if selected in a way consistent with the filtering requirements */ if ( ANIMCHANNEL_SELOK(SEL_NLT(nlt)) ) { /* only include if this track is active */ - // XXX keep this? if (!(filter_mode & ANIMFILTER_ACTIVE) || (nlt->flag & NLATRACK_ACTIVE)) { ale= make_new_animlistelem(nlt, ANIMTYPE_NLATRACK, owner, ownertype, owner_id); diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c index 118dc988dfb..80982d9feb5 100644 --- a/source/blender/editors/space_nla/nla_buttons.c +++ b/source/blender/editors/space_nla/nla_buttons.c @@ -97,13 +97,16 @@ static void do_nla_region_buttons(bContext *C, void *arg, int event) } /* default for now */ - //WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob); + WM_event_add_notifier(C, NC_SCENE|NC_OBJECT|ND_TRANSFORM, NULL); } -static int nla_panel_context(const bContext *C, bAnimListElem **ale, NlaTrack **nlt) +static int nla_panel_context(const bContext *C, PointerRNA *nlt_ptr, PointerRNA *strip_ptr) { bAnimContext ac; - bAnimListElem *elem= NULL; + bAnimListElem *ale= NULL; + ListBase anim_data = {NULL, NULL}; + short found=0; + int filter; /* for now, only draw if we could init the anim-context info (necessary for all animation-related tools) * to work correctly is able to be correctly retrieved. There's no point showing empty panels? @@ -111,20 +114,32 @@ static int nla_panel_context(const bContext *C, bAnimListElem **ale, NlaTrack ** if (ANIM_animdata_get_context(C, &ac) == 0) return 0; - // XXX - return 1; + /* 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); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - /* try to find 'active' F-Curve */ - //elem= get_active_fcurve_channel(&ac); - if(elem == NULL) - return 0; + for (ale= anim_data.first; ale; ale= ale->next) { + if (ale->type == ANIMTYPE_NLATRACK) { + NlaTrack *nlt= (NlaTrack *)ale->data; + + /* found it, now set the pointers */ + 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; + break; + } + } - if(nlt) - *nlt= (NlaTrack*)elem->data; - if(ale) - *ale= elem; - else - MEM_freeN(elem); + /* free temp data */ + BLI_freelistN(&anim_data); return 1; } @@ -134,26 +149,147 @@ static int nla_panel_poll(const bContext *C, PanelType *pt) return nla_panel_context(C, NULL, NULL); } -static void nla_panel_properties(const bContext *C, Panel *pa) -{ - bAnimListElem *ale; - NlaTrack *nlt; - uiBlock *block; - char name[128]; - if(!nla_panel_context(C, &ale, &nlt)) +/* -------------- */ + +/* active NLA-Track */ +static void nla_panel_track (const bContext *C, Panel *pa) +{ + PointerRNA nlt_ptr; + uiLayout *layout= pa->layout; + uiLayout *row; + uiBlock *block; + + /* check context and also validity of pointer */ + if (!nla_panel_context(C, &nlt_ptr, NULL)) + return; + if (nlt_ptr.data == NULL) return; - block= uiLayoutFreeBlock(pa->layout); + block= uiLayoutGetBlock(layout); uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL); - - /* Info - Active F-Curve */ - uiDefBut(block, LABEL, 1, "Active NLA Strip:", 10, 200, 150, 19, NULL, 0.0, 0.0, 0, 0, ""); - - //MEM_freeN(ale); + /* Info - Active NLA-Context:Track ---------------------- */ + row= uiLayoutRow(layout, 1); + uiItemR(row, NULL, ICON_NLA, &nlt_ptr, "name", 0, 0, 0); } +/* generic settings for active NLA-Strip */ +static void nla_panel_properties(const bContext *C, Panel *pa) +{ + PointerRNA strip_ptr; + uiLayout *layout= pa->layout; + uiLayout *column, *row, *subcol; + uiBlock *block; + + /* check context and also validity of pointer */ + if (!nla_panel_context(C, NULL, &strip_ptr)) + return; + if (strip_ptr.data == NULL) + return; + + block= uiLayoutGetBlock(layout); + uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL); + + /* Strip Properties ------------------------------------- */ + /* strip type */ + row= uiLayoutRow(layout, 1); + uiItemR(row, NULL, 0, &strip_ptr, "type", 0, 0, 0); + + /* strip extents */ + column= uiLayoutColumn(layout, 1); + uiItemL(column, "Strip Extents:", 0); + uiItemR(column, NULL, 0, &strip_ptr, "start_frame", 0, 0, 0); + uiItemR(column, NULL, 0, &strip_ptr, "end_frame", 0, 0, 0); + + /* extrapolation */ + row= uiLayoutRow(layout, 1); + uiItemR(row, NULL, 0, &strip_ptr, "extrapolation", 0, 0, 0); + + /* blending */ + row= uiLayoutRow(layout, 1); + uiItemR(row, NULL, 0, &strip_ptr, "blending", 0, 0, 0); + + /* blend in/out + autoblending + * - blend in/out can only be set when autoblending is off + */ + column= uiLayoutColumn(layout, 1); + uiItemR(column, NULL, 0, &strip_ptr, "auto_blending", 0, 0, 0); // XXX as toggle? + subcol= uiLayoutColumn(column, 1); + uiLayoutSetActive(subcol, RNA_boolean_get(&strip_ptr, "auto_blending")==0); + uiItemR(subcol, NULL, 0, &strip_ptr, "blend_in", 0, 0, 0); + uiItemR(subcol, NULL, 0, &strip_ptr, "blend_out", 0, 0, 0); + + /* settings */ + column= uiLayoutColumn(layout, 1); + uiItemL(column, "Playback Settings:", 0); + uiItemR(column, NULL, 0, &strip_ptr, "muted", 0, 0, 0); + uiItemR(column, NULL, 0, &strip_ptr, "reversed", 0, 0, 0); +} + + +/* action-clip only settings for active NLA-Strip */ +static void nla_panel_actclip(const bContext *C, Panel *pa) +{ + PointerRNA strip_ptr; + uiLayout *layout= pa->layout; + uiLayout *column, *row; + uiBlock *block; + + /* check context and also validity of pointer */ + if (!nla_panel_context(C, NULL, &strip_ptr)) + return; + if (strip_ptr.data == NULL) + return; + + // XXX FIXME: move this check into a poll callback + if (RNA_enum_get(&strip_ptr, "type") != NLASTRIP_TYPE_CLIP) + return; + + block= uiLayoutGetBlock(layout); + uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL); + + /* Strip Properties ------------------------------------- */ + /* action pointer */ + row= uiLayoutRow(layout, 1); + uiItemR(row, NULL, ICON_ACTION, &strip_ptr, "action", 0, 0, 0); + + /* action extents */ + // XXX custom names were used here... probably not necessary in future? + column= uiLayoutColumn(layout, 1); + uiItemL(column, "Action Extents:", 0); + uiItemR(column, "Start Frame", 0, &strip_ptr, "action_start_frame", 0, 0, 0); + uiItemR(column, "End Frame", 0, &strip_ptr, "action_end_frame", 0, 0, 0); + + /* action usage */ + column= uiLayoutColumn(layout, 1); + uiItemL(column, "Playback Settings:", 0); + uiItemR(column, NULL, 0, &strip_ptr, "scale", 0, 0, 0); + uiItemR(column, NULL, 0, &strip_ptr, "repeat", 0, 0, 0); +} + +/* evaluation settings for active NLA-Strip */ +static void nla_panel_evaluation(const bContext *C, Panel *pa) +{ + PointerRNA strip_ptr; + uiLayout *layout= pa->layout; + //uiLayout *column, *row, *subcol; + uiBlock *block; + + /* check context and also validity of pointer */ + if (!nla_panel_context(C, NULL, &strip_ptr)) + return; + if (strip_ptr.data == NULL) + return; + + block= uiLayoutGetBlock(layout); + uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL); + + // influence + // strip_time + // animated_influence + // animated_time +} /* ******************* general ******************************** */ @@ -161,13 +297,41 @@ static void nla_panel_properties(const bContext *C, Panel *pa) void nla_buttons_register(ARegionType *art) { PanelType *pt; - + + pt= MEM_callocN(sizeof(PanelType), "spacetype nla panel track"); + strcpy(pt->idname, "NLA_PT_track"); + strcpy(pt->label, "Active Track"); + pt->draw= nla_panel_track; + pt->poll= nla_panel_poll; + BLI_addtail(&art->paneltypes, pt); + pt= MEM_callocN(sizeof(PanelType), "spacetype nla panel properties"); strcpy(pt->idname, "NLA_PT_properties"); - strcpy(pt->label, "Properties"); + strcpy(pt->label, "Active Strip"); pt->draw= nla_panel_properties; pt->poll= nla_panel_poll; BLI_addtail(&art->paneltypes, pt); + + pt= MEM_callocN(sizeof(PanelType), "spacetype nla panel properties"); + strcpy(pt->idname, "NLA_PT_actionclip"); + strcpy(pt->label, "Action Clip"); + pt->draw= nla_panel_actclip; + pt->poll= nla_panel_poll; // XXX need a special one to check for 'action clip' types only + BLI_addtail(&art->paneltypes, pt); + + pt= MEM_callocN(sizeof(PanelType), "spacetype nla panel evaluation"); + strcpy(pt->idname, "NLA_PT_evaluation"); + strcpy(pt->label, "Evaluation"); + pt->draw= nla_panel_evaluation; + pt->poll= nla_panel_poll; + BLI_addtail(&art->paneltypes, pt); + + pt= MEM_callocN(sizeof(PanelType), "spacetype nla panel modifiers"); + strcpy(pt->idname, "NLA_PT_modifiers"); + strcpy(pt->label, "Modifiers"); + //pt->draw= nla_panel_modifiers; + pt->poll= nla_panel_poll; + BLI_addtail(&art->paneltypes, pt); } static int nla_properties(bContext *C, wmOperator *op) From 096e2f0b5ab370fcc01a265ccf77eb71a2f03a43 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 9 Jun 2009 11:26:45 +0000 Subject: [PATCH 029/114] NLA SoC: Transform tools for NLA This commit restores transform support for NLA. Grab, scale, 'extend', and tweak (i.e. grab by just click+dragging) are implemented. Notes: - As soon as one end of a strip touches another adjacent strip (within the same track), that end stops moving. This has been done to avoid the situation where overlapping strips within the same track (which is not allowed) might be caused by transforms. - Made some changes to the RNA setters for the strip extents so that the validation above could take place (and other necessary changes on a per-strip basis could also occur). TODO's ? - Strips cannot be transferred from track to track using transforms. I've yet to decide whether this needs to be done, or whether a separate operator will suffice. - What happens to the range of Actions used when the strips change sizes unexpectedly (i.e. the no-overlap condition above)? Currently range stays the same, but this doesn't always seem desirable? --- source/blender/editors/space_nla/nla_ops.c | 4 +- source/blender/editors/transform/transform.c | 3 + source/blender/editors/transform/transform.h | 7 + .../editors/transform/transform_conversions.c | 195 ++++++++++++++---- .../editors/transform/transform_generics.c | 100 ++++----- .../blender/editors/transform/transform_ops.c | 13 ++ source/blender/makesrna/intern/rna_nla.c | 26 ++- 7 files changed, 251 insertions(+), 97 deletions(-) diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c index f59cbd9c1d4..6505b1deea3 100644 --- a/source/blender/editors/space_nla/nla_ops.c +++ b/source/blender/editors/space_nla/nla_ops.c @@ -54,6 +54,8 @@ #include "ED_space_api.h" #include "ED_screen.h" +#include "BIF_transform.h" + #include "WM_api.h" #include "WM_types.h" @@ -191,7 +193,7 @@ static void nla_keymap_main (wmWindowManager *wm, ListBase *keymap) WM_keymap_add_item(keymap, "NLAEDIT_OT_tweakmode_exit", TABKEY, KM_PRESS, 0, 0); /* transform system */ - //transform_keymap_for_space(wm, keymap, SPACE_NLA); + transform_keymap_for_space(wm, keymap, SPACE_NLA); } /* --------------- */ diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 674de81a9f5..fa93d2a143d 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -319,6 +319,9 @@ static void viewRedrawForce(bContext *C, TransInfo *t) else ED_area_tag_redraw(t->sa); } + else if (t->spacetype == SPACE_NLA) { + ED_area_tag_redraw(t->sa); // XXX this should use a notifier instead! + } else if(t->spacetype == SPACE_NODE) { //ED_area_tag_redraw(t->sa); diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index ee767fada58..c0a57a85033 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -161,6 +161,13 @@ typedef struct TransDataSeq { } TransDataSeq; +/* for NLA transform (stored in td->extra pointer) */ +typedef struct TransDataNla { + struct NlaStrip *strip; /* NLA-strip that handle belongs to */ + float val; /* value for the handle that the transform tools write to */ + int handle; /* handle-index, 0 for start, 1 for end */ +} TransDataNla; + typedef struct TransData { float dist; /* Distance needed to affect element (for Proportionnal Editing) */ float rdist; /* Distance to the nearest element (for Proportionnal Editing) */ diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 6c7aa1ee49d..96f62f1e18e 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -2559,7 +2559,140 @@ int clipUVTransform(TransInfo *t, float *vec, int resize) return (clipx || clipy); } -/* ********************* ACTION/NLA EDITOR ****************** */ +/* ********************* ANIMATION EDITORS (GENERAL) ************************* */ + +/* This function tests if a point is on the "mouse" side of the cursor/frame-marking */ +static short FrameOnMouseSide(char side, float frame, float cframe) +{ + /* both sides, so it doesn't matter */ + if (side == 'B') return 1; + + /* only on the named side */ + if (side == 'R') + return (frame >= cframe) ? 1 : 0; + else + return (frame <= cframe) ? 1 : 0; +} + +/* ********************* NLA EDITOR ************************* */ + +static void createTransNlaData(bContext *C, TransInfo *t) +{ + Scene *scene= CTX_data_scene(C); + TransData *td = NULL; + TransDataNla *tdn = NULL; + + bAnimContext ac; + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + int count=0; + char side; + + /* determine what type of data we are operating on */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return; + + /* filter data */ + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* which side of the current frame should be allowed */ + if (t->mode == TFM_TIME_EXTEND) { + /* only side on which mouse is gets transformed */ + float xmouse, ymouse; + + UI_view2d_region_to_view(&ac.ar->v2d, t->imval[0], t->imval[1], &xmouse, &ymouse); + side = (xmouse > CFRA) ? 'R' : 'L'; // XXX use t->frame_side + } + else { + /* normal transform - both sides of current frame are considered */ + side = 'B'; + } + + /* loop 1: count how many strips are selected (consider each strip as 2 points) */ + for (ale= anim_data.first; ale; ale= ale->next) { + /* only if a real NLA-track */ + if (ale->type == ANIMTYPE_NLATRACK) { + NlaTrack *nlt= (NlaTrack *)ale->data; + NlaStrip *strip; + + /* only consider selected strips */ + for (strip= nlt->strips.first; strip; strip= strip->next) { + // TODO: we can make strips have handles later on... + if (strip->flag & NLASTRIP_FLAG_SELECT) { + if (FrameOnMouseSide(side, strip->start, (float)CFRA)) count++; + if (FrameOnMouseSide(side, strip->end, (float)CFRA)) count++; + } + } + } + } + + /* stop if trying to build list if nothing selected */ + if (count == 0) { + /* cleanup temp list */ + BLI_freelistN(&anim_data); + return; + } + + /* allocate memory for data */ + t->total= count; + + t->data= MEM_callocN(t->total*sizeof(TransData), "TransData(NLA Editor)"); + td= t->data; + t->customData= MEM_callocN(t->total*sizeof(TransDataNla), "TransDataNla (NLA Editor)"); + tdn= t->customData; + + /* loop 2: build transdata array */ + for (ale= anim_data.first; ale; ale= ale->next) { + /* only if a real NLA-track */ + if (ale->type == ANIMTYPE_NLATRACK) { + NlaTrack *nlt= (NlaTrack *)ale->data; + NlaStrip *strip; + + /* only consider selected strips */ + for (strip= nlt->strips.first; strip; strip= strip->next) { + // TODO: we can make strips have handles later on... + if (strip->flag & NLASTRIP_FLAG_SELECT) { + if (FrameOnMouseSide(side, strip->start, (float)CFRA)) + { + /* init the 'extra' data for NLA strip handles first */ + tdn->strip= strip; + tdn->val= strip->start; + tdn->handle= 0; + + /* now, link the transform data up to this data */ + td->val= &tdn->val; + td->ival= tdn->val; + td->extra= tdn; + td++; + tdn++; + } + if (FrameOnMouseSide(side, strip->end, (float)CFRA)) + { + /* init the 'extra' data for NLA strip handles first */ + tdn->strip= strip; + tdn->val= strip->end; + tdn->handle= 1; + + /* now, link the transform data up to this data */ + td->val= &tdn->val; + td->ival= tdn->val; + td->extra= tdn; + td++; + tdn++; + } + } + } + } + } + + /* cleanup temp list */ + BLI_freelistN(&anim_data); +} + +/* ********************* ACTION EDITOR ****************** */ /* Called by special_aftertrans_update to make sure selected gp-frames replace * any other gp-frames which may reside on that frame (that are not selected). @@ -2744,19 +2877,6 @@ static void posttrans_action_clean (bAnimContext *ac, bAction *act) /* ----------------------------- */ -/* This function tests if a point is on the "mouse" side of the cursor/frame-marking */ -static short FrameOnMouseSide(char side, float frame, float cframe) -{ - /* both sides, so it doesn't matter */ - if (side == 'B') return 1; - - /* only on the named side */ - if (side == 'R') - return (frame >= cframe) ? 1 : 0; - else - return (frame <= cframe) ? 1 : 0; -} - /* fully select selected beztriples, but only include if it's on the right side of cfra */ static int count_fcurve_keys(FCurve *fcu, char side, float cfra) { @@ -3044,8 +3164,6 @@ static void createTransActionData(bContext *C, TransInfo *t) /* ********************* GRAPH EDITOR ************************* */ - - /* Helper function for createTransGraphEditData, which is reponsible for associating * source data with transform data */ @@ -3502,7 +3620,6 @@ void flushTransGraphData(TransInfo *t) } } - /* **************** IpoKey stuff, for Object TransData ********** */ /* while transforming */ @@ -4604,6 +4721,29 @@ void special_aftertrans_update(TransInfo *t) /* make sure all F-Curves are set correctly */ ANIM_editkeyframes_refresh(&ac); } + else if (t->spacetype == SPACE_NLA) { + SpaceNla *snla= (SpaceNla *)t->sa->spacedata.first; + Scene *scene; + bAnimContext ac; + + /* initialise relevant anim-context 'context' data from TransInfo data */ + /* NOTE: sync this with the code in ANIM_animdata_get_context() */ + memset(&ac, 0, sizeof(bAnimContext)); + + scene= ac.scene= t->scene; + ob= ac.obact= OBACT; + ac.sa= t->sa; + ac.ar= t->ar; + ac.spacetype= (t->sa)? t->sa->spacetype : 0; + ac.regiontype= (t->ar)? t->ar->regiontype : 0; + + if (ANIM_animdata_context_getdata(&ac) == 0) + return; + + // XXX check on the calls below... we need some of these sanity checks + //synchronize_action_strips(); + //ANIM_editkeyframes_refresh(&ac); + } else if (t->obedit) { // TRANSFORM_FIX_ME // if (t->mode==TFM_BONESIZE || t->mode==TFM_BONE_ENVELOPE) @@ -4682,24 +4822,6 @@ void special_aftertrans_update(TransInfo *t) } } -#if 0 // TRANSFORM_FIX_ME - else if (t->spacetype == SPACE_NLA) { - recalc_all_ipos(); // bad - synchronize_action_strips(); - - /* cleanup */ - for (base=t->scene->base.first; base; base=base->next) - base->flag &= ~(BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA); - - /* after transform, remove duplicate keyframes on a frame that resulted from transform */ - if ( (G.snla->flag & SNLA_NOTRANSKEYCULL)==0 && - ((cancelled == 0) || (duplicate)) ) - { - posttrans_nla_clean(t); - } - } -#endif - clear_trans_object_base_flags(t); #if 0 // TRANSFORM_FIX_ME @@ -4932,8 +5054,7 @@ void createTransData(bContext *C, TransInfo *t) } else if (t->spacetype == SPACE_NLA) { t->flag |= T_POINTS|T_2D_EDIT; - // TRANSFORM_FIX_ME - //createTransNlaData(C, t); + createTransNlaData(C, t); } else if (t->spacetype == SPACE_SEQ) { t->flag |= T_POINTS|T_2D_EDIT; diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 171665c9282..4c9592fb27a 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -102,6 +102,8 @@ #include "BLI_editVert.h" #include "BLI_rand.h" +#include "RNA_access.h" + #include "WM_types.h" #include "UI_resources.h" @@ -299,61 +301,6 @@ void recalcData(TransInfo *t) DAG_object_flush_update(G.scene, OBACT, OB_RECALC_OB|OB_RECALC_DATA); } } - } - else if (t->spacetype == SPACE_NLA) { - if (G.snla->lock) { - for (base=G.scene->base.first; base; base=base->next) { - if (base->flag & BA_HAS_RECALC_OB) - base->object->recalc |= OB_RECALC_OB; - if (base->flag & BA_HAS_RECALC_DATA) - base->object->recalc |= OB_RECALC_DATA; - - if (base->object->recalc) - base->object->ctime= -1234567.0f; // eveil! - - /* recalculate scale of selected nla-strips */ - if (base->object->nlastrips.first) { - Object *bob= base->object; - bActionStrip *strip; - - for (strip= bob->nlastrips.first; strip; strip= strip->next) { - if (strip->flag & ACTSTRIP_SELECT) { - float actlen= strip->actend - strip->actstart; - float len= strip->end - strip->start; - - strip->scale= len / (actlen * strip->repeat); - } - } - } - } - - DAG_scene_flush_update(G.scene, screen_view3d_layers(), 0); - } - else { - for (base=G.scene->base.first; base; base=base->next) { - /* recalculate scale of selected nla-strips */ - if (base->object && base->object->nlastrips.first) { - Object *bob= base->object; - bActionStrip *strip; - - for (strip= bob->nlastrips.first; strip; strip= strip->next) { - if (strip->flag & ACTSTRIP_SELECT) { - float actlen= strip->actend - strip->actstart; - float len= strip->end - strip->start; - - /* prevent 'negative' scaling */ - if (len < 0) { - SWAP(float, strip->start, strip->end); - len= fabs(len); - } - - /* calculate new scale */ - strip->scale= len / (actlen * strip->repeat); - } - } - } - } - } } #endif if (t->obedit) { @@ -422,6 +369,47 @@ void recalcData(TransInfo *t) } } + else if (t->spacetype == SPACE_NLA) { + TransData *td= t->data; + int i; + + /* for each point we've captured, look at its 'extra' data, which is basically a wrapper around the strip + * it is for + some extra storage for the values that get set, and use RNA to set this value (performing validation + * work so that we don't need to repeat it here) + */ + for (i = 0; i < t->total; i++, td++) + { + if (td->extra) + { + TransDataNla *tdn= td->extra; + NlaStrip *strip= tdn->strip; + + /* if we're just cancelling (i.e. the user aborted the transform), + * just restore the data by directly overwriting the values with the original + * ones (i.e. don't go through RNA), as we get some artifacts... + */ + if (t->state == TRANS_CANCEL) { + /* write the value set by the transform tools to the appropriate property using RNA */ + if (tdn->handle) + strip->end= tdn->val; + else + strip->start= tdn->val; + } + else { + PointerRNA strip_ptr; + + /* make RNA-pointer */ + RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr); + + /* write the value set by the transform tools to the appropriate property using RNA */ + if (tdn->handle) + RNA_float_set(&strip_ptr, "end_frame", tdn->val); + else + RNA_float_set(&strip_ptr, "start_frame", tdn->val); + } + } + } + } else if (t->obedit) { if ELEM(t->obedit->type, OB_CURVE, OB_SURF) { Curve *cu= t->obedit->data; @@ -866,7 +854,7 @@ void postTrans (TransInfo *t) if(sima->flag & SI_LIVE_UNWRAP) ED_uvedit_live_unwrap_end(t->state == TRANS_CANCEL); } - else if(t->spacetype==SPACE_ACTION) { + else if(ELEM(t->spacetype, SPACE_ACTION, SPACE_NLA)) { if (t->customData) MEM_freeN(t->customData); } diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 769001b30a8..f7ddd18452e 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -607,6 +607,19 @@ void transform_keymap_for_space(struct wmWindowManager *wm, struct ListBase *key km = WM_keymap_add_item(keymap, "TFM_OT_resize", SKEY, KM_PRESS, 0, 0); break; + case SPACE_NLA: + km= WM_keymap_add_item(keymap, "TFM_OT_transform", GKEY, KM_PRESS, 0, 0); + RNA_int_set(km->ptr, "mode", TFM_TIME_TRANSLATE); + + km= WM_keymap_add_item(keymap, "TFM_OT_transform", EVT_TWEAK_S, KM_ANY, 0, 0); + RNA_int_set(km->ptr, "mode", TFM_TIME_TRANSLATE); + + km= WM_keymap_add_item(keymap, "TFM_OT_transform", EKEY, KM_PRESS, 0, 0); + RNA_int_set(km->ptr, "mode", TFM_TIME_EXTEND); + + km= WM_keymap_add_item(keymap, "TFM_OT_transform", SKEY, KM_PRESS, 0, 0); + RNA_int_set(km->ptr, "mode", TFM_TIME_SCALE); + break; case SPACE_NODE: km= WM_keymap_add_item(keymap, "TFM_OT_translation", GKEY, KM_PRESS, 0, 0); diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c index 0a7d17adc09..b55b4e431fb 100644 --- a/source/blender/makesrna/intern/rna_nla.c +++ b/source/blender/makesrna/intern/rna_nla.c @@ -43,7 +43,18 @@ static void rna_NlaStrip_start_frame_set(PointerRNA *ptr, float value) { NlaStrip *data= (NlaStrip*)ptr->data; - CLAMP(value, 1, data->end); + + /* clamp value to lie within valid limits + * - cannot start past the end of the strip + some flexibility threshold + * - cannot start before the previous strip (if present) ends + * - minimum frame is 1.0f (this can be changed) + */ + if (data->prev) { + CLAMP(value, data->prev->end, data->end-0.1f); + } + else { + CLAMP(value, 1, data->end); + } data->start= value; } @@ -52,8 +63,17 @@ static void rna_NlaStrip_end_frame_set(PointerRNA *ptr, float value) NlaStrip *data= (NlaStrip*)ptr->data; float len, actlen; - /* clamp value to lie within valid limits - must not have zero or negative length strip */ - CLAMP(value, data->start+0.1f, MAXFRAME); + /* clamp value to lie within valid limits + * - must not have zero or negative length strip, so cannot start before the first frame + * + some minimum-strip-length threshold + * - cannot end later than the start of the next strip (if present) + */ + if (data->next) { + CLAMP(value, data->start+0.1f, data->next->start); + } + else { + CLAMP(value, data->start+0.1f, MAXFRAME); + } data->end= value; /* calculate the lengths the strip and its action (if applicable) */ From ca5ff43b1f3efa555b1e52d190c5a97332e01e85 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 9 Jun 2009 12:28:10 +0000 Subject: [PATCH 030/114] NLA SoC: Improved anim-channel filtering flags for NLA so that channels don't need to be checked to be NLA-Tracks before being used. --- .../blender/editors/animation/anim_filter.c | 16 ++++++------- source/blender/editors/include/ED_anim_api.h | 3 ++- source/blender/editors/space_nla/nla_select.c | 4 ++-- .../editors/transform/transform_conversions.c | 23 ++++++++----------- 4 files changed, 22 insertions(+), 24 deletions(-) diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index cdda13d999d..6cb24a01711 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -1050,7 +1050,7 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B int items = 0; /* add this object as a channel first */ - if ((filter_mode & ANIMFILTER_CURVESONLY) == 0) { + 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); @@ -1062,7 +1062,7 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B } /* if collapsed, don't go any further (unless adding keyframes only) */ - if ( (EXPANDED_OBJC(ob) == 0) && !(filter_mode & ANIMFILTER_CURVESONLY) ) + if ( (EXPANDED_OBJC(ob) == 0) && !(filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) ) return items; /* Action, Drivers, or NLA */ @@ -1073,7 +1073,7 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B { /* nla */ #if 0 /* include nla-expand widget? */ - if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) { + if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_NLATRACKS)) { ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLNLA, base, ANIMTYPE_OBJECT, (ID *)ob); if (ale) { BLI_addtail(anim_data, ale); @@ -1129,7 +1129,7 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B { /* nla */ #if 0 /* include nla-expand widget? */ - if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) { + if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_NLATRACKS)) { ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLNLA, base, ANIMTYPE_OBJECT, (ID *)ob); if (ale) { BLI_addtail(anim_data, ale); @@ -1235,7 +1235,7 @@ static int animdata_filter_dopesheet_scene (ListBase *anim_data, bDopeSheet *ads int items = 0; /* add scene as a channel first (even if we aren't showing scenes we still need to show the scene's sub-data */ - if ((filter_mode & ANIMFILTER_CURVESONLY) == 0) { + if ((filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) == 0) { /* check if filtering by selection */ if (ANIMCHANNEL_SELOK( (sce->flag & SCE_DS_SELECTED) )) { ale= make_new_animlistelem(sce, ANIMTYPE_SCENE, NULL, ANIMTYPE_NONE, NULL); @@ -1247,7 +1247,7 @@ static int animdata_filter_dopesheet_scene (ListBase *anim_data, bDopeSheet *ads } /* if collapsed, don't go any further (unless adding keyframes only) */ - if ( (EXPANDED_SCEC(sce) == 0) && !(filter_mode & ANIMFILTER_CURVESONLY) ) + if ( (EXPANDED_SCEC(sce) == 0) && !(filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) ) return items; /* Action, Drivers, or NLA for Scene */ @@ -1258,7 +1258,7 @@ static int animdata_filter_dopesheet_scene (ListBase *anim_data, bDopeSheet *ads { /* nla */ #if 0 /* include nla-expand widget? */ - if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) { + if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_NLATRACKS)) { ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLNLA, base, ANIMTYPE_SCENE (ID *)sce); if (ale) { BLI_addtail(anim_data, ale); @@ -1312,7 +1312,7 @@ static int animdata_filter_dopesheet_scene (ListBase *anim_data, bDopeSheet *ads { /* nla */ #if 0 /* include nla-expand widget? */ - if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) { + if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_NLATRACKS)) { ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLNLA, base, ANIMTYPE_DSWOR (ID *)wo); if (ale) { BLI_addtail(anim_data, ale); diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index dcaabb4b369..e44c7ff5603 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -162,8 +162,9 @@ typedef enum eAnimFilter_Flags { ANIMFILTER_CHANNELS = (1<<5), /* make list for interface drawing */ ANIMFILTER_ACTGROUPED = (1<<6), /* belongs to the active actiongroup */ ANIMFILTER_CURVEVISIBLE = (1<<7), /* F-Curve is visible for editing/viewing in Graph Editor */ - ANIMFILTER_ACTIVE = (1<<8), /* channel should be 'active' */ // FIXME: this is only relevant for F-Curves for now + ANIMFILTER_ACTIVE = (1<<8), /* channel should be 'active' */ ANIMFILTER_ANIMDATA = (1<<9), /* only return the underlying AnimData blocks (not the tracks, etc.) data comes from */ + ANIMFILTER_NLATRACKS = (1<<10), /* only include NLA-tracks */ } eAnimFilter_Flags; diff --git a/source/blender/editors/space_nla/nla_select.c b/source/blender/editors/space_nla/nla_select.c index 463479c0909..730814dc562 100644 --- a/source/blender/editors/space_nla/nla_select.c +++ b/source/blender/editors/space_nla/nla_select.c @@ -120,8 +120,8 @@ static void deselect_nla_strips (bAnimContext *ac, short test, short sel) int filter; short smode; - /* determine type-based settings - curvesonly eliminates all the unnecessary channels... */ - filter= (ANIMFILTER_VISIBLE|ANIMFILTER_CURVESONLY); + /* determine type-based settings */ + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS); /* filter data */ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 96f62f1e18e..fb7d9c57eaf 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -2595,7 +2595,7 @@ static void createTransNlaData(bContext *C, TransInfo *t) return; /* filter data */ - filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT); + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT); ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); /* which side of the current frame should be allowed */ @@ -2613,18 +2613,15 @@ static void createTransNlaData(bContext *C, TransInfo *t) /* loop 1: count how many strips are selected (consider each strip as 2 points) */ for (ale= anim_data.first; ale; ale= ale->next) { - /* only if a real NLA-track */ - if (ale->type == ANIMTYPE_NLATRACK) { - NlaTrack *nlt= (NlaTrack *)ale->data; - NlaStrip *strip; - - /* only consider selected strips */ - for (strip= nlt->strips.first; strip; strip= strip->next) { - // TODO: we can make strips have handles later on... - if (strip->flag & NLASTRIP_FLAG_SELECT) { - if (FrameOnMouseSide(side, strip->start, (float)CFRA)) count++; - if (FrameOnMouseSide(side, strip->end, (float)CFRA)) count++; - } + NlaTrack *nlt= (NlaTrack *)ale->data; + NlaStrip *strip; + + /* only consider selected strips */ + for (strip= nlt->strips.first; strip; strip= strip->next) { + // TODO: we can make strips have handles later on... + if (strip->flag & NLASTRIP_FLAG_SELECT) { + if (FrameOnMouseSide(side, strip->start, (float)CFRA)) count++; + if (FrameOnMouseSide(side, strip->end, (float)CFRA)) count++; } } } From abdb8fd94d90a1b9fb262c94dac1ccb52cfee36f Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 9 Jun 2009 12:28:49 +0000 Subject: [PATCH 031/114] NLA SoC: Added simple delete-strips operator (XKEY/DELKEY) --- source/blender/editors/space_nla/nla_edit.c | 63 ++++++++++++++++++- source/blender/editors/space_nla/nla_intern.h | 5 ++ source/blender/editors/space_nla/nla_ops.c | 6 ++ 3 files changed, 73 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index 49d43f29c5f..ce62d36e667 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -68,7 +68,7 @@ #include "nla_intern.h" // own include /* *********************************************** */ -/* General Editing */ +/* 'Special' Editing */ /* ******************** Tweak-Mode Operators ***************************** */ /* 'Tweak mode' allows the action referenced by the active NLA-strip to be edited @@ -211,5 +211,66 @@ void NLAEDIT_OT_tweakmode_exit (wmOperatorType *ot) } /* *********************************************** */ +/* NLA Editing Operations */ + +/* ******************** Delete Operator ***************************** */ +/* Deletes the selected NLA-Strips */ + +static int nlaedit_delete_exec (bContext *C, wmOperator *op) +{ + bAnimContext ac; + + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* get a list of the AnimData blocks being shown in the NLA */ + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* for each NLA-Track, delete all selected strips */ + // FIXME: need to double-check that we've got tracks + for (ale= anim_data.first; ale; ale= ale->next) { + NlaTrack *nlt= (NlaTrack *)ale->data; + NlaStrip *strip, *nstrip; + + for (strip= nlt->strips.first; strip; strip= nstrip) { + nstrip= strip->next; + + /* if selected, delete */ + if (strip->flag & NLASTRIP_FLAG_SELECT) + free_nlastrip(&nlt->strips, strip); + } + } + + /* free temp data */ + BLI_freelistN(&anim_data); + + /* set notifier that things have changed */ + ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); + WM_event_add_notifier(C, NC_SCENE, NULL); + + /* done */ + return OPERATOR_FINISHED; +} + +void NLAEDIT_OT_delete (wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Delete Strips"; + ot->idname= "NLAEDIT_OT_delete"; + ot->description= "Delete selected strips."; + + /* api callbacks */ + ot->exec= nlaedit_delete_exec; + ot->poll= nlaop_poll_tweakmode_off; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} /* *********************************************** */ diff --git a/source/blender/editors/space_nla/nla_intern.h b/source/blender/editors/space_nla/nla_intern.h index 00de0498e4b..abbb7331e28 100644 --- a/source/blender/editors/space_nla/nla_intern.h +++ b/source/blender/editors/space_nla/nla_intern.h @@ -89,6 +89,11 @@ void NLAEDIT_OT_click_select(wmOperatorType *ot); void NLAEDIT_OT_tweakmode_enter(wmOperatorType *ot); void NLAEDIT_OT_tweakmode_exit(wmOperatorType *ot); +/* --- */ + +void NLAEDIT_OT_delete(wmOperatorType *ot); + + /* **************************************** */ /* nla_channels.c */ diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c index 6505b1deea3..3eb32d147f5 100644 --- a/source/blender/editors/space_nla/nla_ops.c +++ b/source/blender/editors/space_nla/nla_ops.c @@ -131,6 +131,8 @@ void nla_operatortypes(void) /* edit */ WM_operatortype_append(NLAEDIT_OT_tweakmode_enter); WM_operatortype_append(NLAEDIT_OT_tweakmode_exit); + + WM_operatortype_append(NLAEDIT_OT_delete); } /* ************************** registration - keymaps **********************************/ @@ -191,6 +193,10 @@ static void nla_keymap_main (wmWindowManager *wm, ListBase *keymap) */ WM_keymap_add_item(keymap, "NLAEDIT_OT_tweakmode_enter", TABKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "NLAEDIT_OT_tweakmode_exit", TABKEY, KM_PRESS, 0, 0); + + /* delete */ + WM_keymap_add_item(keymap, "NLAEDIT_OT_delete", XKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "NLAEDIT_OT_delete", DELKEY, KM_PRESS, 0, 0); /* transform system */ transform_keymap_for_space(wm, keymap, SPACE_NLA); From 2f8290434ca1e36c8a60ebc405a3edaacd41e9a9 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Wed, 10 Jun 2009 04:43:18 +0000 Subject: [PATCH 032/114] NLA SoC: Added BorderSelect operators (BKEY and Alt-BKEY) These work in the same way as the ones in the Action Editor... --- .../blender/editors/space_nla/nla_channels.c | 4 +- source/blender/editors/space_nla/nla_intern.h | 1 + source/blender/editors/space_nla/nla_ops.c | 6 + source/blender/editors/space_nla/nla_select.c | 145 ++++++++++++++++++ 4 files changed, 154 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c index ed401c3596b..b40b1bf0f4d 100644 --- a/source/blender/editors/space_nla/nla_channels.c +++ b/source/blender/editors/space_nla/nla_channels.c @@ -179,7 +179,7 @@ void NLA_OT_channels_select_border(wmOperatorType *ot) ot->exec= nlachannels_borderselect_exec; ot->modal= WM_border_select_modal; - ot->poll= ED_operator_areaactive; + ot->poll= nlaop_poll_tweakmode_off; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -449,7 +449,7 @@ void NLA_OT_channels_click (wmOperatorType *ot) /* api callbacks */ ot->invoke= nlachannels_mouseclick_invoke; - ot->poll= ED_operator_areaactive; + ot->poll= nlaop_poll_tweakmode_off; // xxx? /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; diff --git a/source/blender/editors/space_nla/nla_intern.h b/source/blender/editors/space_nla/nla_intern.h index abbb7331e28..94e907a59db 100644 --- a/source/blender/editors/space_nla/nla_intern.h +++ b/source/blender/editors/space_nla/nla_intern.h @@ -81,6 +81,7 @@ enum { /* --- */ void NLAEDIT_OT_select_all_toggle(wmOperatorType *ot); +void NLAEDIT_OT_select_border(wmOperatorType *ot); void NLAEDIT_OT_click_select(wmOperatorType *ot); /* **************************************** */ diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c index 3eb32d147f5..61654338fea 100644 --- a/source/blender/editors/space_nla/nla_ops.c +++ b/source/blender/editors/space_nla/nla_ops.c @@ -126,6 +126,7 @@ void nla_operatortypes(void) /* select */ WM_operatortype_append(NLAEDIT_OT_click_select); + WM_operatortype_append(NLAEDIT_OT_select_border); WM_operatortype_append(NLAEDIT_OT_select_all_toggle); /* edit */ @@ -186,6 +187,11 @@ static void nla_keymap_main (wmWindowManager *wm, ListBase *keymap) WM_keymap_add_item(keymap, "NLAEDIT_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0); RNA_boolean_set(WM_keymap_add_item(keymap, "NLAEDIT_OT_select_all_toggle", IKEY, KM_PRESS, KM_CTRL, 0)->ptr, "invert", 1); + /* borderselect */ + WM_keymap_add_item(keymap, "NLAEDIT_OT_select_border", BKEY, KM_PRESS, 0, 0); + RNA_boolean_set(WM_keymap_add_item(keymap, "NLAEDIT_OT_select_border", BKEY, KM_PRESS, KM_ALT, 0)->ptr, "axis_range", 1); + + /* editing */ /* tweakmode * - enter and exit are separate operators with the same hotkey... diff --git a/source/blender/editors/space_nla/nla_select.c b/source/blender/editors/space_nla/nla_select.c index 730814dc562..25a876d44f4 100644 --- a/source/blender/editors/space_nla/nla_select.c +++ b/source/blender/editors/space_nla/nla_select.c @@ -208,6 +208,151 @@ void NLAEDIT_OT_select_all_toggle (wmOperatorType *ot) RNA_def_boolean(ot->srna, "invert", 0, "Invert", ""); } +/* ******************** Border Select Operator **************************** */ +/* This operator currently works in one of three ways: + * -> BKEY - 1) all strips within region are selected (ACTKEYS_BORDERSEL_ALLSTRIPS) + * -> ALT-BKEY - depending on which axis of the region was larger... + * -> 2) x-axis, so select all frames within frame range (ACTKEYS_BORDERSEL_FRAMERANGE) + * -> 3) y-axis, so select all frames within channels that region included (ACTKEYS_BORDERSEL_CHANNELS) + */ + +/* defines for borderselect mode */ +enum { + NLA_BORDERSEL_ALLSTRIPS = 0, + NLA_BORDERSEL_FRAMERANGE, + NLA_BORDERSEL_CHANNELS, +} eActKeys_BorderSelect_Mode; + + +static void borderselect_nla_strips (bAnimContext *ac, rcti rect, short mode, short selectmode) +{ + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + View2D *v2d= &ac->ar->v2d; + rctf rectf; + float ymin=(float)(-NLACHANNEL_HEIGHT), ymax=0; + + /* convert border-region to view coordinates */ + UI_view2d_region_to_view(v2d, rect.xmin, rect.ymin+2, &rectf.xmin, &rectf.ymin); + UI_view2d_region_to_view(v2d, rect.xmax, rect.ymax-2, &rectf.xmax, &rectf.ymax); + + /* filter data */ + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CHANNELS); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + /* convert selection modes to selection modes */ + selectmode= selmodes_to_flagmodes(selectmode); + + /* loop over data, doing border select */ + for (ale= anim_data.first; ale; ale= ale->next) { + ymax= ymin + NLACHANNEL_STEP; + + /* perform vertical suitability check (if applicable) */ + if ( (mode == NLA_BORDERSEL_FRAMERANGE) || + !((ymax < rectf.ymin) || (ymin > rectf.ymax)) ) + { + /* loop over data selecting (only if NLA-Track) */ + if (ale->type == ANIMTYPE_NLATRACK) { + NlaTrack *nlt= (NlaTrack *)ale->data; + NlaStrip *strip; + + /* only select strips if they fall within the required ranges (if applicable) */ + for (strip= nlt->strips.first; strip; strip= strip->next) { + if ( (mode == NLA_BORDERSEL_CHANNELS) || + BKE_nlastrip_within_bounds(strip, rectf.xmin, rectf.xmax) ) + { + /* set selection */ + ACHANNEL_SET_FLAG(strip, selectmode, NLASTRIP_FLAG_SELECT); + + /* clear active flag */ + strip->flag &= ~NLASTRIP_FLAG_ACTIVE; + } + } + } + } + + /* set maximum extent to be the minimum of the next channel */ + ymin= ymax; + } + + /* cleanup */ + BLI_freelistN(&anim_data); +} + +/* ------------------- */ + +static int nlaedit_borderselect_exec(bContext *C, wmOperator *op) +{ + bAnimContext ac; + rcti rect; + short mode=0, selectmode=0; + int event; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* get settings from operator */ + rect.xmin= RNA_int_get(op->ptr, "xmin"); + rect.ymin= RNA_int_get(op->ptr, "ymin"); + rect.xmax= RNA_int_get(op->ptr, "xmax"); + rect.ymax= RNA_int_get(op->ptr, "ymax"); + + event= RNA_int_get(op->ptr, "event_type"); + if (event == LEFTMOUSE) // FIXME... hardcoded + selectmode = SELECT_ADD; + else + selectmode = SELECT_SUBTRACT; + + /* selection 'mode' depends on whether borderselect region only matters on one axis */ + if (RNA_boolean_get(op->ptr, "axis_range")) { + /* mode depends on which axis of the range is larger to determine which axis to use + * - checking this in region-space is fine, as it's fundamentally still going to be a different rect size + * - the frame-range select option is favoured over the channel one (x over y), as frame-range one is often + * used for tweaking timing when "blocking", while channels is not that useful... + */ + if ((rect.xmax - rect.xmin) >= (rect.ymax - rect.ymin)) + mode= NLA_BORDERSEL_FRAMERANGE; + else + mode= NLA_BORDERSEL_CHANNELS; + } + else + mode= NLA_BORDERSEL_ALLSTRIPS; + + /* apply borderselect action */ + borderselect_nla_strips(&ac, rect, mode, selectmode); + + return OPERATOR_FINISHED; +} + +void NLAEDIT_OT_select_border(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Border Select"; + ot->idname= "NLAEDIT_OT_select_border"; + + /* api callbacks */ + ot->invoke= WM_border_select_invoke; + ot->exec= nlaedit_borderselect_exec; + ot->modal= WM_border_select_modal; + + ot->poll= nlaop_poll_tweakmode_off; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* rna */ + RNA_def_int(ot->srna, "event_type", 0, INT_MIN, INT_MAX, "Event Type", "", INT_MIN, INT_MAX); + RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX); + 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_boolean(ot->srna, "axis_range", 0, "Axis Range", ""); +} + /* ******************** Mouse-Click Select Operator *********************** */ /* This operator works in one of 2 ways: * 1) Select the strip directly under the mouse From 867e1291350de7c128c18c9f9a2e7c4b7a5513f4 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Wed, 10 Jun 2009 05:03:27 +0000 Subject: [PATCH 033/114] F-Modifiers (in Nla branch): For fun, added 'sinc' (i.e. y = sin(pi*x)/(pi*x)) as a type of builtin function usable through the generator modifier. This makes a nice 'jolt' which tapers off. --- source/blender/blenkernel/intern/fcurve.c | 17 ++++++++++++++++- .../blender/editors/space_graph/graph_buttons.c | 5 ++++- source/blender/makesdna/DNA_anim_types.h | 1 + source/blender/makesrna/intern/rna_fcurve.c | 1 + 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 6a3870f8f31..5820761234c 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -1410,6 +1410,18 @@ static void fcm_generator_verify (FModifier *fcm) } } +/* Unary 'normalised sine' function + * y = sin(PI + x) / (PI * x), + * except for x = 0 when y = 1. + */ +static double sinc (double x) +{ + if (fabs(x) < 0.0001) + return 1.0; + else + return sin(M_PI * x) / (M_PI * x); +} + static void fcm_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) { FMod_Generator *data= (FMod_Generator *)fcm->data; @@ -1490,6 +1502,9 @@ static void fcm_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, case FCM_GENERATOR_FN_COS: /* cosine wave */ fn= cos; break; + case FCM_GENERATOR_FN_SINC: /* normalised sine wave */ + fn= sinc; + break; /* validation required */ case FCM_GENERATOR_FN_TAN: /* tangent wave */ @@ -1527,7 +1542,7 @@ static void fcm_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, } } break; - + default: printf("Invalid Function-Generator for F-Modifier - %d \n", data->func_type); } diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c index a4babaad74c..5b00205b5d0 100644 --- a/source/blender/editors/space_graph/graph_buttons.c +++ b/source/blender/editors/space_graph/graph_buttons.c @@ -405,7 +405,7 @@ static void draw_modifier__generator(uiBlock *block, FCurve *fcu, FModifier *fcm { FMod_Generator *data= (FMod_Generator *)fcm->data; char gen_mode[]="Generator Type%t|Expanded Polynomial%x0|Factorised Polynomial%x1|Built-In Function%x2|Expression%x3"; - char fn_type[]="Built-In Function%t|Sin%x0|Cos%x1|Tan%x2|Square Root%x3|Natural Log%x4"; + char fn_type[]="Built-In Function%t|Sin%x0|Cos%x1|Tan%x2|Square Root%x3|Natural Log%x4|Normalised Sin%x5"; int cy= *yco - 30; uiBut *but; @@ -555,6 +555,9 @@ static void draw_modifier__generator(uiBlock *block, FCurve *fcu, FModifier *fcm case FCM_GENERATOR_FN_SQRT: /* square root */ sprintf(func_name, "sqrt("); break; + case FCM_GENERATOR_FN_SINC: /* normalised sine wave */ + sprintf(func_name, "sinc("); + break; default: /* unknown */ sprintf(func_name, "("); break; diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h index c19318629f6..a784adaf35f 100644 --- a/source/blender/makesdna/DNA_anim_types.h +++ b/source/blender/makesdna/DNA_anim_types.h @@ -108,6 +108,7 @@ enum { FCM_GENERATOR_FN_TAN, FCM_GENERATOR_FN_SQRT, FCM_GENERATOR_FN_LN, + FCM_GENERATOR_FN_SINC, } eFMod_Generator_Functions; diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c index ea26118f267..69103536310 100644 --- a/source/blender/makesrna/intern/rna_fcurve.c +++ b/source/blender/makesrna/intern/rna_fcurve.c @@ -284,6 +284,7 @@ static void rna_def_fmodifier_generator_function(BlenderRNA *brna) {2, "TAN", "Tangent", ""}, {3, "SQRT", "Square Root", ""}, {4, "LN", "Natural Logarithm", ""}, + {5, "SINC", "Normalised Sine", "sin(x) / x"}, {0, NULL, NULL, NULL}}; From 64f94a670ea9a5704276f1e80f61afdcb067a2b6 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 11 Jun 2009 02:14:56 +0000 Subject: [PATCH 034/114] NLA SoC: Evaluation bugfixes * Strip scaling was being evaluated in the wrong way, resulting in scaled strips not being played too fast (for lengthened strips) or too slow (shortened strips) * Also, verified that the 'reversed' option works correctly (no changes needed to be made here) --- source/blender/blenkernel/intern/anim_sys.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 3290e06dfb4..a864e3d4e87 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -591,23 +591,23 @@ static float nlastrip_get_frame (NlaStrip *strip, float cframe, short invert) float length, actlength, repeat, scale; /* get number of repeats */ - if (strip->repeat == 0.0f) strip->repeat = 1.0f; + if (IS_EQ(strip->repeat, 0.0f)) strip->repeat = 1.0f; repeat = strip->repeat; /* scaling */ - if (strip->scale == 0.0f) strip->scale= 1.0f; + if (IS_EQ(strip->scale, 0.0f)) strip->scale= 1.0f; scale = (float)fabs(strip->scale); /* scale must be positive - we've got a special flag for reversing */ /* length of referenced action */ actlength = strip->actend - strip->actstart; - if (actlength == 0.0f) actlength = 1.0f; + if (IS_EQ(actlength, 0.0f)) actlength = 1.0f; /* length of strip */ - length = repeat * scale * actlength; + length = strip->end - strip->start; + if (IS_EQ(length, 0.0f)) length= actlength * scale * repeat; /* reversed = play strip backwards */ if (strip->flag & NLASTRIP_FLAG_REVERSE) { - // FIXME: verify these /* invert = convert action-strip time to global time */ if (invert) return length*(strip->actend - cframe)/(repeat*actlength) + strip->start; @@ -651,7 +651,7 @@ void nlastrip_evaluate_controls (NlaStrip *strip, float ctime) { /* firstly, analytically generate values for influence and time (if applicable) */ if ((strip->flag & NLASTRIP_FLAG_USR_TIME) == 0) - strip->strip_time= nlastrip_get_frame(strip, ctime, 1); /* last arg '1' means current time to 'strip'/action time */ + strip->strip_time= nlastrip_get_frame(strip, ctime, 0); if ((strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) == 0) strip->influence= nlastrip_get_influence(strip, ctime); From 4a29d0c1a36359c3e08a90beb80cd40857305c80 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 11 Jun 2009 02:18:29 +0000 Subject: [PATCH 035/114] NLA SoC: 'Split' Operator (YKEY) Selected NLA Strips are split into two strips, each with half the length of the original strip. Possible improvements subject to demand: - multiple splits? - splits with variable spacing? (i.e. 3:2, or 1:5). --- source/blender/editors/space_nla/nla_edit.c | 97 ++++++++++++++++++- source/blender/editors/space_nla/nla_intern.h | 1 + source/blender/editors/space_nla/nla_ops.c | 4 + 3 files changed, 100 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index ce62d36e667..93ac726c17e 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -49,6 +49,7 @@ #include "BKE_context.h" #include "BKE_report.h" #include "BKE_screen.h" +#include "BKE_utildefines.h" #include "ED_anim_api.h" #include "ED_markers.h" @@ -213,7 +214,7 @@ void NLAEDIT_OT_tweakmode_exit (wmOperatorType *ot) /* *********************************************** */ /* NLA Editing Operations */ -/* ******************** Delete Operator ***************************** */ +/* ******************** Delete Strips Operator ***************************** */ /* Deletes the selected NLA-Strips */ static int nlaedit_delete_exec (bContext *C, wmOperator *op) @@ -233,7 +234,6 @@ static int nlaedit_delete_exec (bContext *C, wmOperator *op) ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); /* for each NLA-Track, delete all selected strips */ - // FIXME: need to double-check that we've got tracks for (ale= anim_data.first; ale; ale= ale->next) { NlaTrack *nlt= (NlaTrack *)ale->data; NlaStrip *strip, *nstrip; @@ -273,4 +273,97 @@ void NLAEDIT_OT_delete (wmOperatorType *ot) ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } +/* ******************** Split Strips Operator ***************************** */ +/* Splits the selected NLA-Strips into two strips at the midpoint of the strip */ +// TODO's? +// - multiple splits +// - variable-length splits? + +static int nlaedit_split_exec (bContext *C, wmOperator *op) +{ + bAnimContext ac; + + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* get a list of the AnimData blocks being shown in the NLA */ + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* for each NLA-Track, delete all selected strips */ + for (ale= anim_data.first; ale; ale= ale->next) { + NlaTrack *nlt= (NlaTrack *)ale->data; + NlaStrip *strip, *nstrip, *next; + + for (strip= nlt->strips.first; strip; strip= next) { + next= strip->next; + + /* if selected, split the strip at its midpoint */ + if (strip->flag & NLASTRIP_FLAG_SELECT) { + float midframe, midaframe, len; + + /* calculate the frames to do the splitting at */ + /* strip extents */ + len= strip->end - strip->start; + if (IS_EQ(len, 0.0f)) + continue; + else + midframe= strip->start + (len / 2.0f); + + /* action range */ + len= strip->actend - strip->actstart; + if (IS_EQ(len, 0.0f)) + midaframe= strip->actend; + else + midaframe= strip->actstart + (len / 2.0f); + + /* make a copy (assume that this is possible) and append + * it immediately after the current strip + */ + nstrip= copy_nlastrip(strip); + BLI_insertlinkafter(&nlt->strips, strip, nstrip); + + /* set the endpoint of the first strip and the start of the new strip + * to the midframe values calculated above + */ + strip->end= midframe; + nstrip->start= midframe; + + strip->actend= midaframe; + nstrip->actstart= midaframe; + } + } + } + + /* free temp data */ + BLI_freelistN(&anim_data); + + /* set notifier that things have changed */ + ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); + WM_event_add_notifier(C, NC_SCENE, NULL); + + /* done */ + return OPERATOR_FINISHED; +} + +void NLAEDIT_OT_split (wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Split Strips"; + ot->idname= "NLAEDIT_OT_split"; + ot->description= "Split selected strips at their midpoints."; + + /* api callbacks */ + ot->exec= nlaedit_split_exec; + ot->poll= nlaop_poll_tweakmode_off; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + /* *********************************************** */ diff --git a/source/blender/editors/space_nla/nla_intern.h b/source/blender/editors/space_nla/nla_intern.h index 94e907a59db..9511f67f824 100644 --- a/source/blender/editors/space_nla/nla_intern.h +++ b/source/blender/editors/space_nla/nla_intern.h @@ -93,6 +93,7 @@ void NLAEDIT_OT_tweakmode_exit(wmOperatorType *ot); /* --- */ void NLAEDIT_OT_delete(wmOperatorType *ot); +void NLAEDIT_OT_split(wmOperatorType *ot); /* **************************************** */ diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c index 61654338fea..14c6f2a32d2 100644 --- a/source/blender/editors/space_nla/nla_ops.c +++ b/source/blender/editors/space_nla/nla_ops.c @@ -134,6 +134,7 @@ void nla_operatortypes(void) WM_operatortype_append(NLAEDIT_OT_tweakmode_exit); WM_operatortype_append(NLAEDIT_OT_delete); + WM_operatortype_append(NLAEDIT_OT_split); } /* ************************** registration - keymaps **********************************/ @@ -204,6 +205,9 @@ static void nla_keymap_main (wmWindowManager *wm, ListBase *keymap) WM_keymap_add_item(keymap, "NLAEDIT_OT_delete", XKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "NLAEDIT_OT_delete", DELKEY, KM_PRESS, 0, 0); + /* split */ + WM_keymap_add_item(keymap, "NLAEDIT_OT_split", YKEY, KM_PRESS, 0, 0); + /* transform system */ transform_keymap_for_space(wm, keymap, SPACE_NLA); } From f0f9034966be8692250686aee74048294960aad3 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 11 Jun 2009 03:19:08 +0000 Subject: [PATCH 036/114] NLA SoC: Operator for adding new NLA-Tracks New tracks can be added in the following ways (with the mouse hovering over the channels-list): * Shift-A - this will add a new track at the top of the stack (i.e. above all the existing NLA-tracks but below the Active Action) for every AnimData block where there was a selected NLA-Track * Ctrl-Shift-A - this will add a new track above every selected one --- source/blender/blenkernel/BKE_nla.h | 2 +- source/blender/blenkernel/intern/nla.c | 13 +++- .../blender/editors/space_nla/nla_channels.c | 73 +++++++++++++++++++ source/blender/editors/space_nla/nla_edit.c | 1 + source/blender/editors/space_nla/nla_intern.h | 2 + source/blender/editors/space_nla/nla_ops.c | 9 ++- 6 files changed, 94 insertions(+), 6 deletions(-) diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index da824fd2093..078c1ba52bb 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -46,7 +46,7 @@ struct NlaStrip *copy_nlastrip(struct NlaStrip *strip); struct NlaTrack *copy_nlatrack(struct NlaTrack *nlt); void copy_nladata(ListBase *dst, ListBase *src); -struct NlaTrack *add_nlatrack(struct AnimData *adt); +struct NlaTrack *add_nlatrack(struct AnimData *adt, struct NlaTrack *prev); struct NlaStrip *add_nlastrip(struct bAction *act); struct NlaStrip *add_nlastrip_to_stack(struct AnimData *adt, struct bAction *act); diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 9acbad32a42..cef14128032 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -215,8 +215,10 @@ void copy_nladata (ListBase *dst, ListBase *src) /* Adding ------------------------------------------- */ -/* Add a NLA Track to the given AnimData */ -NlaTrack *add_nlatrack (AnimData *adt) +/* Add a NLA Track to the given AnimData + * - prev: NLA-Track to add the new one after + */ +NlaTrack *add_nlatrack (AnimData *adt, NlaTrack *prev) { NlaTrack *nlt; @@ -232,7 +234,10 @@ NlaTrack *add_nlatrack (AnimData *adt) nlt->index= BLI_countlist(&adt->nla_tracks); /* add track to stack, and make it the active one */ - BLI_addtail(&adt->nla_tracks, nlt); + if (prev) + BLI_insertlinkafter(&adt->nla_tracks, prev, nlt); + else + BLI_addtail(&adt->nla_tracks, nlt); BKE_nlatrack_set_active(&adt->nla_tracks, nlt); /* must have unique name, but we need to seed this */ @@ -308,7 +313,7 @@ NlaStrip *add_nlastrip_to_stack (AnimData *adt, bAction *act) (BKE_nlatrack_has_space(adt->nla_tracks.last, strip->start, strip->end)==0) ) { /* no space, so add to a new track... */ - nlt= add_nlatrack(adt); + nlt= add_nlatrack(adt, NULL); } else { diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c index b40b1bf0f4d..992c5bfa756 100644 --- a/source/blender/editors/space_nla/nla_channels.c +++ b/source/blender/editors/space_nla/nla_channels.c @@ -459,3 +459,76 @@ void NLA_OT_channels_click (wmOperatorType *ot) } /* *********************************************** */ +/* Special Operators */ + +/* ******************** Add Tracks Operator ***************************** */ +/* Add NLA Tracks to the same AnimData block as a selected track, or above the selected tracks */ + +static int nlaedit_add_tracks_exec (bContext *C, wmOperator *op) +{ + bAnimContext ac; + + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + AnimData *lastAdt = NULL; + short above_sel= RNA_boolean_get(op->ptr, "above_selected"); + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* get a list of the AnimData blocks being shown in the NLA */ + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_SEL); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* add tracks... */ + for (ale= anim_data.first; ale; ale= ale->next) { + NlaTrack *nlt= (NlaTrack *)ale->data; + AnimData *adt= BKE_animdata_from_id(ale->id); + + /* check if just adding a new track above this one, + * or whether we're adding a new one to the top of the stack that this one belongs to + */ + if (above_sel) { + /* just add a new one above this one */ + add_nlatrack(adt, nlt); + } + else if ((lastAdt == NULL) || (adt != lastAdt)) { + /* add one track to the top of the owning AnimData's stack, then don't add anymore to this stack */ + add_nlatrack(adt, NULL); + lastAdt= adt; + } + } + + /* free temp data */ + BLI_freelistN(&anim_data); + + /* set notifier that things have changed */ + ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); + WM_event_add_notifier(C, NC_SCENE, NULL); + + /* done */ + return OPERATOR_FINISHED; +} + +void NLA_OT_add_tracks (wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Add Track(s)"; + ot->idname= "NLA_OT_add_tracks"; + ot->description= "Add NLA-Tracks above/after the selected tracks."; + + /* api callbacks */ + ot->exec= nlaedit_add_tracks_exec; + ot->poll= nlaop_poll_tweakmode_off; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* properties */ + RNA_def_boolean(ot->srna, "above_selected", 0, "Above Selected", "Add a new NLA Track above every existing selected one."); +} + +/* *********************************************** */ diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index 93ac726c17e..e8af67aebd1 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -28,6 +28,7 @@ #include #include +#include #include "DNA_anim_types.h" #include "DNA_action_types.h" diff --git a/source/blender/editors/space_nla/nla_intern.h b/source/blender/editors/space_nla/nla_intern.h index 9511f67f824..b0a9ba5b182 100644 --- a/source/blender/editors/space_nla/nla_intern.h +++ b/source/blender/editors/space_nla/nla_intern.h @@ -102,6 +102,8 @@ void NLAEDIT_OT_split(wmOperatorType *ot); void NLA_OT_channels_select_border(wmOperatorType *ot); void NLA_OT_channels_click(wmOperatorType *ot); +void NLA_OT_add_tracks(wmOperatorType *ot); + /* **************************************** */ /* nla_ops.c */ diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c index 14c6f2a32d2..6cba19bb2cf 100644 --- a/source/blender/editors/space_nla/nla_ops.c +++ b/source/blender/editors/space_nla/nla_ops.c @@ -124,6 +124,8 @@ void nla_operatortypes(void) WM_operatortype_append(NLA_OT_channels_click); WM_operatortype_append(NLA_OT_channels_select_border); + WM_operatortype_append(NLA_OT_add_tracks); + /* select */ WM_operatortype_append(NLAEDIT_OT_click_select); WM_operatortype_append(NLAEDIT_OT_select_border); @@ -148,9 +150,14 @@ static void nla_keymap_channels (wmWindowManager *wm, ListBase *keymap) WM_keymap_add_item(keymap, "NLA_OT_channels_click", LEFTMOUSE, KM_PRESS, 0, 0); RNA_boolean_set(WM_keymap_add_item(keymap, "NLA_OT_channels_click", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "extend", 1); - /* borderselect */ + /* borderselect */ WM_keymap_add_item(keymap, "NLA_OT_channels_select_border", BKEY, KM_PRESS, 0, 0); + /* channel operations */ + /* add tracks */ + WM_keymap_add_item(keymap, "NLA_OT_add_tracks", AKEY, KM_PRESS, KM_SHIFT, 0); + RNA_boolean_set(WM_keymap_add_item(keymap, "NLA_OT_add_tracks", AKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0)->ptr, "above_selected", 1); + /* General Animation Channels keymap (see anim_channels.c) ----------------------- */ /* deselect all */ WM_keymap_add_item(keymap, "ANIM_OT_channels_select_all_toggle", AKEY, KM_PRESS, 0, 0); From 0bef8012bc71b1a1d3fae4f5ef82055045ef4752 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 11 Jun 2009 05:02:46 +0000 Subject: [PATCH 037/114] NLA SoC: Channel ordering change In response to user-feedback, I've changed the order in which channels appear. Now, the channel ordering is: - Object/AnimData block -- Active Action -- Last NLA Track .. .. -- First NLA Track It is important to note several things still: 1) Active action is applied AFTER the NLA Tracks have been evaluated, not before 2) In this new order, the tracks+active action are shown in the evaluation-stack order, i.e. first thing applied is at the bottom, last is at the top. As a result, I've switched the view-orientation back so that it works the same way as for DopeSheet/Graph editors (i.e. expands downwards not upwards). This may cause problems loading files saved with older builds of this branch. There are still some lingering problems due to this change which I'll fix in due course. --- .../blender/editors/animation/anim_channels.c | 8 ++ .../blender/editors/animation/anim_filter.c | 72 +++++++---- .../blender/editors/space_nla/nla_buttons.c | 2 +- .../blender/editors/space_nla/nla_channels.c | 112 +----------------- source/blender/editors/space_nla/nla_draw.c | 46 ++++--- source/blender/editors/space_nla/nla_intern.h | 1 - source/blender/editors/space_nla/nla_ops.c | 8 +- source/blender/editors/space_nla/nla_select.c | 8 +- source/blender/editors/space_nla/space_nla.c | 61 +++++----- 9 files changed, 116 insertions(+), 202 deletions(-) diff --git a/source/blender/editors/animation/anim_channels.c b/source/blender/editors/animation/anim_channels.c index 59fb56f3c35..2944c9519b9 100644 --- a/source/blender/editors/animation/anim_channels.c +++ b/source/blender/editors/animation/anim_channels.c @@ -1216,6 +1216,14 @@ static void borderselect_anim_channels (bAnimContext *ac, rcti *rect, short sele ACHANNEL_SET_FLAG(gpl, selectmode, GP_LAYER_SELECT); } break; + + case ANIMTYPE_NLATRACK: /* nla-track */ + { + NlaTrack *nlt= (NlaTrack *)ale->data; + + ACHANNEL_SET_FLAG(nlt, selectmode, NLATRACK_SELECTED); + } + break; } } diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index 6cb24a01711..b47211f35d1 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -717,36 +717,21 @@ static int animdata_filter_action (ListBase *anim_data, bAction *act, int filter return items; } +/* Include NLA-Data for NLA-Editor: + * - when ANIMFILTER_CHANNELS is used, that means we should be filtering the list for display + * Although the evaluation order is from the first track to the last and then apply the Action on top, + * we present this in the UI as the Active Action followed by the last track to the first so that we + * get the evaluation order presented as per a stack. + * - for normal filtering (i.e. for editing), we only need the NLA-tracks but they can be in 'normal' evaluation + * order, i.e. first to last. Otherwise, some tools may get screwed up. + */ static int animdata_filter_nla (ListBase *anim_data, AnimData *adt, int filter_mode, void *owner, short ownertype, ID *owner_id) { bAnimListElem *ale; NlaTrack *nlt; + NlaTrack *first=NULL, *next=NULL; int items = 0; - /* loop over NLA Tracks - assume that the caller of this has already checked that these should be included */ - for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) { - /* only work with this channel and its subchannels if it is editable */ - if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_NLT(nlt)) { - /* only include this track if selected in a way consistent with the filtering requirements */ - if ( ANIMCHANNEL_SELOK(SEL_NLT(nlt)) ) { - /* only include if this track is active */ - if (!(filter_mode & ANIMFILTER_ACTIVE) || (nlt->flag & NLATRACK_ACTIVE)) { - ale= make_new_animlistelem(nlt, ANIMTYPE_NLATRACK, owner, ownertype, owner_id); - - if (ale) { - BLI_addtail(anim_data, ale); - items++; - } - } - - /* if we're in NLA-tweakmode, if this track was active, that means that it was the last active one */ - // FIXME: the channels after should still get drawn, just 'differently', and after an active-action channel - if ((adt->flag & ADT_NLA_EDIT_ON) && (nlt->flag & NLATRACK_ACTIVE)) - break; - } - } - } - /* if showing channels, include active action */ if (filter_mode & ANIMFILTER_CHANNELS) { /* there isn't really anything editable here, so skip if need editable */ @@ -764,6 +749,45 @@ static int animdata_filter_nla (ListBase *anim_data, AnimData *adt, int filter_m items++; } } + + /* first track to include will be the last one if we're filtering by channels */ + first= adt->nla_tracks.last; + } + else { + /* first track to include will the the first one (as per normal) */ + first= adt->nla_tracks.first; + } + + /* loop over NLA Tracks - assume that the caller of this has already checked that these should be included */ + for (nlt= first; nlt; nlt= next) { + /* 'next' NLA-Track to use depends on whether we're filtering for drawing or not */ + if (filter_mode & ANIMFILTER_CHANNELS) + next= nlt->prev; + else + next= nlt->next; + + /* if we're in NLA-tweakmode, don't show this track if it was disabled (due to tweaking) for now + * - active track should still get shown though (even though it has disabled flag set) + */ + // FIXME: the channels after should still get drawn, just 'differently', and after an active-action channel + if ((adt->flag & ADT_NLA_EDIT_ON) && (nlt->flag & NLATRACK_DISABLED) && !(nlt->flag & NLATRACK_ACTIVE)) + continue; + + /* only work with this channel and its subchannels if it is editable */ + if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_NLT(nlt)) { + /* only include this track if selected in a way consistent with the filtering requirements */ + if ( ANIMCHANNEL_SELOK(SEL_NLT(nlt)) ) { + /* only include if this track is active */ + if (!(filter_mode & ANIMFILTER_ACTIVE) || (nlt->flag & NLATRACK_ACTIVE)) { + ale= make_new_animlistelem(nlt, ANIMTYPE_NLATRACK, owner, ownertype, owner_id); + + if (ale) { + BLI_addtail(anim_data, ale); + items++; + } + } + } + } } /* return the number of items added to the list */ diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c index 80982d9feb5..cb21dd66934 100644 --- a/source/blender/editors/space_nla/nla_buttons.c +++ b/source/blender/editors/space_nla/nla_buttons.c @@ -141,7 +141,7 @@ static int nla_panel_context(const bContext *C, PointerRNA *nlt_ptr, PointerRNA /* free temp data */ BLI_freelistN(&anim_data); - return 1; + return found; } static int nla_panel_poll(const bContext *C, PanelType *pt) diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c index 992c5bfa756..f928daa523b 100644 --- a/source/blender/editors/space_nla/nla_channels.c +++ b/source/blender/editors/space_nla/nla_channels.c @@ -82,116 +82,6 @@ /* *********************************************** */ /* Operators for NLA channels-list which need to be different from the standard Animation Editor ones */ -/* ******************** Borderselect Operator *********************** */ - -static void borderselect_nla_channels (bAnimContext *ac, rcti *rect, short selectmode) -{ - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - - View2D *v2d= &ac->ar->v2d; - rctf rectf; - float ymin=(float)(-NLACHANNEL_HEIGHT), ymax=0; - - /* convert border-region to view coordinates */ - UI_view2d_region_to_view(v2d, rect->xmin, rect->ymin+2, &rectf.xmin, &rectf.ymin); - UI_view2d_region_to_view(v2d, rect->xmax, rect->ymax-2, &rectf.xmax, &rectf.ymax); - - /* filter data */ - filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CHANNELS); - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - - /* loop over data, doing border select */ - for (ale= anim_data.first; ale; ale= ale->next) { - ymax= ymin + NLACHANNEL_STEP; - - /* if channel is within border-select region, alter it */ - if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))) { - /* only the following types can be selected */ - switch (ale->type) { - case ANIMTYPE_OBJECT: /* object */ - { - Base *base= (Base *)ale->data; - Object *ob= base->object; - - ACHANNEL_SET_FLAG(base, selectmode, SELECT); - ACHANNEL_SET_FLAG(ob, selectmode, SELECT); - } - break; - case ANIMTYPE_NLATRACK: /* nla-track */ - { - NlaTrack *nlt= (NlaTrack *)ale->data; - - ACHANNEL_SET_FLAG(nlt, selectmode, NLATRACK_SELECTED); - } - break; - } - } - - /* set maximum extent to be the minimum of the next channel */ - ymin= ymax; - } - - /* cleanup */ - BLI_freelistN(&anim_data); -} - -/* ------------------- */ - -static int nlachannels_borderselect_exec(bContext *C, wmOperator *op) -{ - bAnimContext ac; - rcti rect; - short selectmode=0; - int event; - - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; - - /* get settings from operator */ - rect.xmin= RNA_int_get(op->ptr, "xmin"); - rect.ymin= RNA_int_get(op->ptr, "ymin"); - rect.xmax= RNA_int_get(op->ptr, "xmax"); - rect.ymax= RNA_int_get(op->ptr, "ymax"); - - event= RNA_int_get(op->ptr, "event_type"); - if (event == LEFTMOUSE) // FIXME... hardcoded - selectmode = ACHANNEL_SETFLAG_ADD; - else - selectmode = ACHANNEL_SETFLAG_CLEAR; - - /* apply borderselect animation channels */ - borderselect_nla_channels(&ac, &rect, selectmode); - - return OPERATOR_FINISHED; -} - -void NLA_OT_channels_select_border(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Border Select"; - ot->idname= "NLA_OT_channels_select_border"; - - /* api callbacks */ - ot->invoke= WM_border_select_invoke; - ot->exec= nlachannels_borderselect_exec; - ot->modal= WM_border_select_modal; - - ot->poll= nlaop_poll_tweakmode_off; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - /* rna */ - RNA_def_int(ot->srna, "event_type", 0, INT_MIN, INT_MAX, "Event Type", "", INT_MIN, INT_MAX); - RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX); - 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); -} - /* ******************** Mouse-Click Operator *********************** */ /* Depending on the channel that was clicked on, the mouse click will activate whichever * part of the channel is relevant. @@ -425,7 +315,7 @@ static int nlachannels_mouseclick_invoke(bContext *C, wmOperator *op, wmEvent *e selectmode= SELECT_REPLACE; /* figure out which channel user clicked in - * Note: although channels technically start at y= ACHANNEL_FIRST, we need to adjust by half a channel's height + * Note: although channels technically start at y= NLACHANNEL_FIRST, we need to adjust by half a channel's height * so that the tops of channels get caught ok. Since NLACHANNEL_FIRST is really NLACHANNEL_HEIGHT, we simply use * NLACHANNEL_HEIGHT_HALF. */ diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index 4fa27f4bc11..8d417a150aa 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -250,15 +250,13 @@ void draw_nla_main_data (bAnimContext *ac, SpaceNla *snla, ARegion *ar) * start of list offset, and the second is as a correction for the scrollers. */ height= ((items*NLACHANNEL_STEP) + (NLACHANNEL_HEIGHT*2)); - if (height > (v2d->mask.ymax - v2d->mask.ymin)) { - /* don't use totrect set, as the width stays the same - * (NOTE: this is ok here, the configuration is pretty straightforward) - */ - v2d->tot.ymax= (float)(height); - } + /* don't use totrect set, as the width stays the same + * (NOTE: this is ok here, the configuration is pretty straightforward) + */ + v2d->tot.ymin= (float)(-height); /* loop through channels, and set up drawing depending on their type */ - y= (float)(-NLACHANNEL_FIRST); + y= (float)(-NLACHANNEL_HEIGHT); for (ale= anim_data.first; ale; ale= ale->next) { const float yminc= (float)(y - NLACHANNEL_HEIGHT_HALF); @@ -330,7 +328,7 @@ void draw_nla_main_data (bAnimContext *ac, SpaceNla *snla, ARegion *ar) } /* adjust y-position for next one */ - y += NLACHANNEL_STEP; + y -= NLACHANNEL_STEP; } /* free tempolary channels */ @@ -361,15 +359,13 @@ void draw_nla_channel_list (bAnimContext *ac, SpaceNla *snla, ARegion *ar) * start of list offset, and the second is as a correction for the scrollers. */ height= ((items*NLACHANNEL_STEP) + (NLACHANNEL_HEIGHT*2)); - if (height > (v2d->mask.ymax - v2d->mask.ymin)) { - /* don't use totrect set, as the width stays the same - * (NOTE: this is ok here, the configuration is pretty straightforward) - */ - v2d->tot.ymax= (float)(height); - } + /* don't use totrect set, as the width stays the same + * (NOTE: this is ok here, the configuration is pretty straightforward) + */ + v2d->tot.ymin= (float)(-height); /* loop through channels, and set up drawing depending on their type */ - y= (float)(-NLACHANNEL_FIRST); + y= (float)(-NLACHANNEL_HEIGHT); for (ale= anim_data.first; ale; ale= ale->next) { const float yminc= (float)(y - NLACHANNEL_HEIGHT_HALF); @@ -397,7 +393,7 @@ void draw_nla_channel_list (bAnimContext *ac, SpaceNla *snla, ARegion *ar) /* only show expand if there are any channels */ if (EXPANDED_SCEC(sce)) - expand= ICON_TRIA_UP; + expand= ICON_TRIA_DOWN; else expand= ICON_TRIA_RIGHT; @@ -421,7 +417,7 @@ void draw_nla_channel_list (bAnimContext *ac, SpaceNla *snla, ARegion *ar) /* only show expand if there are any channels */ if (EXPANDED_OBJC(ob)) - expand= ICON_TRIA_UP; + expand= ICON_TRIA_DOWN; else expand= ICON_TRIA_RIGHT; @@ -438,7 +434,7 @@ void draw_nla_channel_list (bAnimContext *ac, SpaceNla *snla, ARegion *ar) special = ICON_MATERIAL_DATA; if (FILTER_MAT_OBJC(ob)) - expand = ICON_TRIA_UP; + expand = ICON_TRIA_DOWN; else expand = ICON_TRIA_RIGHT; @@ -457,7 +453,7 @@ void draw_nla_channel_list (bAnimContext *ac, SpaceNla *snla, ARegion *ar) offset = 21; if (FILTER_MAT_OBJD(ma)) - expand = ICON_TRIA_UP; + expand = ICON_TRIA_DOWN; else expand = ICON_TRIA_RIGHT; @@ -473,7 +469,7 @@ void draw_nla_channel_list (bAnimContext *ac, SpaceNla *snla, ARegion *ar) special = ICON_LAMP_DATA; if (FILTER_LAM_OBJD(la)) - expand = ICON_TRIA_UP; + expand = ICON_TRIA_DOWN; else expand = ICON_TRIA_RIGHT; @@ -489,7 +485,7 @@ void draw_nla_channel_list (bAnimContext *ac, SpaceNla *snla, ARegion *ar) special = ICON_CAMERA_DATA; if (FILTER_CAM_OBJD(ca)) - expand = ICON_TRIA_UP; + expand = ICON_TRIA_DOWN; else expand = ICON_TRIA_RIGHT; @@ -505,7 +501,7 @@ void draw_nla_channel_list (bAnimContext *ac, SpaceNla *snla, ARegion *ar) special = ICON_CURVE_DATA; if (FILTER_CUR_OBJD(cu)) - expand = ICON_TRIA_UP; + expand = ICON_TRIA_DOWN; else expand = ICON_TRIA_RIGHT; @@ -521,7 +517,7 @@ void draw_nla_channel_list (bAnimContext *ac, SpaceNla *snla, ARegion *ar) special = ICON_SHAPEKEY_DATA; // XXX if (FILTER_SKE_OBJD(key)) - expand = ICON_TRIA_UP; + expand = ICON_TRIA_DOWN; else expand = ICON_TRIA_RIGHT; @@ -629,7 +625,7 @@ void draw_nla_channel_list (bAnimContext *ac, SpaceNla *snla, ARegion *ar) if (ELEM(ale->type, ANIMTYPE_SCENE, ANIMTYPE_OBJECT)) { /* object channel - darker */ UI_ThemeColor(TH_DOPESHEET_CHANNELOB); - uiSetRoundBox((expand == ICON_TRIA_UP)? (8):(1|8)); + uiSetRoundBox((expand == ICON_TRIA_DOWN)? (8):(1|8)); gl_round_box(GL_POLYGON, x+offset, yminc, (float)NLACHANNEL_NAMEWIDTH, ymaxc, 10); } else { @@ -763,7 +759,7 @@ void draw_nla_channel_list (bAnimContext *ac, SpaceNla *snla, ARegion *ar) } /* adjust y-position for next one */ - y += NLACHANNEL_STEP; + y -= NLACHANNEL_STEP; } /* free tempolary channels */ diff --git a/source/blender/editors/space_nla/nla_intern.h b/source/blender/editors/space_nla/nla_intern.h index b0a9ba5b182..5c6670cfd6f 100644 --- a/source/blender/editors/space_nla/nla_intern.h +++ b/source/blender/editors/space_nla/nla_intern.h @@ -99,7 +99,6 @@ void NLAEDIT_OT_split(wmOperatorType *ot); /* **************************************** */ /* nla_channels.c */ -void NLA_OT_channels_select_border(wmOperatorType *ot); void NLA_OT_channels_click(wmOperatorType *ot); void NLA_OT_add_tracks(wmOperatorType *ot); diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c index 6cba19bb2cf..981ef9a4f87 100644 --- a/source/blender/editors/space_nla/nla_ops.c +++ b/source/blender/editors/space_nla/nla_ops.c @@ -122,7 +122,6 @@ void nla_operatortypes(void) /* channels */ WM_operatortype_append(NLA_OT_channels_click); - WM_operatortype_append(NLA_OT_channels_select_border); WM_operatortype_append(NLA_OT_add_tracks); @@ -150,15 +149,16 @@ static void nla_keymap_channels (wmWindowManager *wm, ListBase *keymap) WM_keymap_add_item(keymap, "NLA_OT_channels_click", LEFTMOUSE, KM_PRESS, 0, 0); RNA_boolean_set(WM_keymap_add_item(keymap, "NLA_OT_channels_click", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "extend", 1); - /* borderselect */ - WM_keymap_add_item(keymap, "NLA_OT_channels_select_border", BKEY, KM_PRESS, 0, 0); - /* channel operations */ /* add tracks */ WM_keymap_add_item(keymap, "NLA_OT_add_tracks", AKEY, KM_PRESS, KM_SHIFT, 0); RNA_boolean_set(WM_keymap_add_item(keymap, "NLA_OT_add_tracks", AKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0)->ptr, "above_selected", 1); /* General Animation Channels keymap (see anim_channels.c) ----------------------- */ + /* selection */ + /* borderselect */ + WM_keymap_add_item(keymap, "ANIM_OT_channels_select_border", BKEY, KM_PRESS, 0, 0); + /* deselect all */ WM_keymap_add_item(keymap, "ANIM_OT_channels_select_all_toggle", AKEY, KM_PRESS, 0, 0); RNA_boolean_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_select_all_toggle", IKEY, KM_PRESS, KM_CTRL, 0)->ptr, "invert", 1); diff --git a/source/blender/editors/space_nla/nla_select.c b/source/blender/editors/space_nla/nla_select.c index 25a876d44f4..b850ec76f82 100644 --- a/source/blender/editors/space_nla/nla_select.c +++ b/source/blender/editors/space_nla/nla_select.c @@ -247,7 +247,7 @@ static void borderselect_nla_strips (bAnimContext *ac, rcti rect, short mode, sh /* loop over data, doing border select */ for (ale= anim_data.first; ale; ale= ale->next) { - ymax= ymin + NLACHANNEL_STEP; + ymin= ymax - NLACHANNEL_STEP; /* perform vertical suitability check (if applicable) */ if ( (mode == NLA_BORDERSEL_FRAMERANGE) || @@ -273,8 +273,8 @@ static void borderselect_nla_strips (bAnimContext *ac, rcti rect, short mode, sh } } - /* set maximum extent to be the minimum of the next channel */ - ymin= ymax; + /* set minimum extent to be the maximum of the next channel */ + ymax= ymin; } /* cleanup */ @@ -390,7 +390,7 @@ static void mouse_nla_strips (bAnimContext *ac, int mval[2], short select_mode) /* use View2D to determine the index of the channel (i.e a row in the list) where keyframe was */ UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y); - UI_view2d_listview_view_to_cell(v2d, 0, NLACHANNEL_STEP, 0, 0, x, y, NULL, &channel_index); + UI_view2d_listview_view_to_cell(v2d, 0, NLACHANNEL_STEP, 0, (float)NLACHANNEL_HEIGHT_HALF, x, y, NULL, &channel_index); /* x-range to check is +/- 7 (in screen/region-space) on either side of mouse click * (that is the size of keyframe icons, so user should be expecting similar tolerances) diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c index 5490f40eb03..a7e9844726d 100644 --- a/source/blender/editors/space_nla/space_nla.c +++ b/source/blender/editors/space_nla/space_nla.c @@ -103,6 +103,7 @@ ARegion *nla_has_buttons_region(ScrArea *sa) static SpaceLink *nla_new(const bContext *C) { + Scene *scene= CTX_data_scene(C); ARegion *ar; SpaceNla *snla; @@ -132,37 +133,6 @@ static SpaceLink *nla_new(const bContext *C) ar->v2d.scroll = V2D_SCROLL_BOTTOM; ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL; - /* main area */ - ar= MEM_callocN(sizeof(ARegion), "main area for nla"); - - BLI_addtail(&snla->regionbase, ar); - ar->regiontype= RGN_TYPE_WINDOW; - - ar->v2d.tot.xmin= 1.0f; - ar->v2d.tot.ymin= 0.0f; - ar->v2d.tot.xmax= 1000.0f; - ar->v2d.tot.ymax= 500.0f; - - ar->v2d.cur.xmin= -5.0f; - ar->v2d.cur.ymin= 0.0f; - ar->v2d.cur.xmax= 65.0f; - ar->v2d.cur.ymax= 250.0f; - - ar->v2d.min[0]= 0.0f; - ar->v2d.min[1]= 0.0f; - - ar->v2d.max[0]= MAXFRAMEF; - ar->v2d.max[1]= 1000.0f; - - ar->v2d.minzoom= 0.1f; - ar->v2d.maxzoom= 50.0f; - - ar->v2d.scroll = (V2D_SCROLL_BOTTOM|V2D_SCROLL_SCALE_HORIZONTAL); - ar->v2d.scroll |= (V2D_SCROLL_RIGHT); - ar->v2d.keepzoom= V2D_LOCKZOOM_Y; - ar->v2d.align= V2D_ALIGN_NO_NEG_Y; - ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL; - /* ui buttons */ ar= MEM_callocN(sizeof(ARegion), "buttons area for nla"); @@ -171,6 +141,33 @@ static SpaceLink *nla_new(const bContext *C) ar->alignment= RGN_ALIGN_RIGHT; ar->flag = RGN_FLAG_HIDDEN; + /* main area */ + ar= MEM_callocN(sizeof(ARegion), "main area for nla"); + + BLI_addtail(&snla->regionbase, ar); + ar->regiontype= RGN_TYPE_WINDOW; + + ar->v2d.tot.xmin= (float)(SFRA-10); + ar->v2d.tot.ymin= -500.0f; + ar->v2d.tot.xmax= (float)(EFRA+10); + ar->v2d.tot.ymax= 0.0f; + + ar->v2d.cur = ar->v2d.tot; + + ar->v2d.min[0]= 0.0f; + ar->v2d.min[1]= 0.0f; + + ar->v2d.max[0]= MAXFRAMEF; + ar->v2d.max[1]= 10000.0f; + + ar->v2d.minzoom= 0.01f; + ar->v2d.maxzoom= 50; + ar->v2d.scroll = (V2D_SCROLL_BOTTOM|V2D_SCROLL_SCALE_HORIZONTAL); + ar->v2d.scroll |= (V2D_SCROLL_RIGHT); + ar->v2d.keepzoom= V2D_LOCKZOOM_Y; + ar->v2d.align= V2D_ALIGN_NO_POS_Y; + ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL; + return (SpaceLink *)snla; } @@ -213,7 +210,7 @@ static void nla_channel_area_init(wmWindowManager *wm, ARegion *ar) { ListBase *keymap; - UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_STACK, ar->winx, ar->winy); + UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy); /* own keymap */ // TODO: cannot use generic copy, need special NLA version From cdeb95e737f6995b3b4cb2ced1a966f787167c1b Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 11 Jun 2009 11:53:41 +0000 Subject: [PATCH 038/114] NLA SoC: RNA Fixes - Lower bound for start values has been expanded to -MAXFRAME, to avoid clipping problems when the strip is moved past frame 0 - Removed some obsolete (+ commented out) NLA wrapping in Object stuff --- source/blender/makesrna/intern/rna_nla.c | 6 +++--- source/blender/makesrna/intern/rna_object.c | 23 --------------------- 2 files changed, 3 insertions(+), 26 deletions(-) diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c index b55b4e431fb..4b5c14aab82 100644 --- a/source/blender/makesrna/intern/rna_nla.c +++ b/source/blender/makesrna/intern/rna_nla.c @@ -47,13 +47,13 @@ static void rna_NlaStrip_start_frame_set(PointerRNA *ptr, float value) /* clamp value to lie within valid limits * - cannot start past the end of the strip + some flexibility threshold * - cannot start before the previous strip (if present) ends - * - minimum frame is 1.0f (this can be changed) + * - minimum frame is -MAXFRAME so that we don't get clipping on frame 0 */ if (data->prev) { CLAMP(value, data->prev->end, data->end-0.1f); } else { - CLAMP(value, 1, data->end); + CLAMP(value, -MAXFRAME, data->end); } data->start= value; } @@ -137,7 +137,7 @@ static void rna_NlaStrip_blend_out_set(PointerRNA *ptr, float value) static void rna_NlaStrip_action_start_frame_set(PointerRNA *ptr, float value) { NlaStrip *data= (NlaStrip*)ptr->data; - CLAMP(value, 1, data->actend); + CLAMP(value, -MAXFRAME, data->actend); data->actstart= value; } diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index 08eca7b0528..edfaf5cb21a 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -1069,29 +1069,6 @@ static StructRNA *rna_def_object(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Pose Mode", "Object with armature data is in pose mode."); - // XXX this stuff should be moved to AnimData... -/* - prop= RNA_def_property(srna, "nla_disable_path", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "nlaflag", OB_DISABLE_PATH); - RNA_def_property_ui_text(prop, "NLA Disable Path", "Disable path temporally, for editing cycles."); - - prop= RNA_def_property(srna, "nla_collapsed", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "nlaflag", OB_NLA_COLLAPSED); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "NLA Collapsed", ""); - - prop= RNA_def_property(srna, "nla_override", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "nlaflag", OB_NLA_OVERRIDE); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "NLA Override", ""); - - prop= RNA_def_property(srna, "nla_strips", PROP_COLLECTION, PROP_NONE); - RNA_def_property_collection_sdna(prop, NULL, "nlastrips", NULL); - RNA_def_property_struct_type(prop, "UnknownType"); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "NLA Strips", "NLA strips of the object."); -*/ - /* shape keys */ prop= RNA_def_property(srna, "shape_key_lock", PROP_BOOLEAN, PROP_NONE); From 4f9846b6a13184c504682853beb2647b4a77e9ac Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 12 Jun 2009 02:49:21 +0000 Subject: [PATCH 039/114] NLA SoC: Fixes for crashes when selecting keyframes in object channels in DopeSheet --- .../blender/editors/animation/anim_filter.c | 48 +------------------ .../editors/animation/keyframes_edit.c | 24 +++++++++- .../editors/space_action/action_select.c | 26 +++++----- 3 files changed, 38 insertions(+), 60 deletions(-) diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index b47211f35d1..f9c1b1bb42f 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -1095,17 +1095,6 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B ANIMDATA_FILTER_CASES(ob, { /* AnimData blocks - do nothing... */ }, { /* nla */ -#if 0 - /* include nla-expand widget? */ - if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_NLATRACKS)) { - ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLNLA, base, ANIMTYPE_OBJECT, (ID *)ob); - if (ale) { - BLI_addtail(anim_data, ale); - items++; - } - } -#endif - /* add NLA tracks */ items += animdata_filter_nla(anim_data, adt, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob); }, @@ -1141,7 +1130,7 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B items += animdata_filter_action(anim_data, adt->action, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob); } } - ) + ); } @@ -1151,17 +1140,6 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B ANIMDATA_FILTER_CASES(key, { /* AnimData blocks - do nothing... */ }, { /* nla */ -#if 0 - /* include nla-expand widget? */ - if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_NLATRACKS)) { - ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLNLA, base, ANIMTYPE_OBJECT, (ID *)ob); - if (ale) { - BLI_addtail(anim_data, ale); - items++; - } - } -#endif - /* add NLA tracks */ items += animdata_filter_nla(anim_data, adt, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob); }, @@ -1195,7 +1173,7 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B items += animdata_filter_shapekey(anim_data, key, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob); } } - ) + ); } /* Materials? */ @@ -1280,17 +1258,6 @@ static int animdata_filter_dopesheet_scene (ListBase *anim_data, bDopeSheet *ads ANIMDATA_FILTER_CASES(sce, { /* AnimData blocks - do nothing... */ }, { /* nla */ -#if 0 - /* include nla-expand widget? */ - if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_NLATRACKS)) { - ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLNLA, base, ANIMTYPE_SCENE (ID *)sce); - if (ale) { - BLI_addtail(anim_data, ale); - items++; - } - } -#endif - /* add NLA tracks */ items += animdata_filter_nla(anim_data, adt, filter_mode, sce, ANIMTYPE_SCENE, (ID *)sce); }, @@ -1334,17 +1301,6 @@ static int animdata_filter_dopesheet_scene (ListBase *anim_data, bDopeSheet *ads ANIMDATA_FILTER_CASES(wo, { /* AnimData blocks - do nothing... */ }, { /* nla */ -#if 0 - /* include nla-expand widget? */ - if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_NLATRACKS)) { - ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLNLA, base, ANIMTYPE_DSWOR (ID *)wo); - if (ale) { - BLI_addtail(anim_data, ale); - items++; - } - } -#endif - /* add NLA tracks */ items += animdata_filter_nla(anim_data, adt, filter_mode, wo, ANIMTYPE_DSWOR, (ID *)wo); }, diff --git a/source/blender/editors/animation/keyframes_edit.c b/source/blender/editors/animation/keyframes_edit.c index 8243629b4a6..77826eca87a 100644 --- a/source/blender/editors/animation/keyframes_edit.c +++ b/source/blender/editors/animation/keyframes_edit.c @@ -128,6 +128,10 @@ static short agrp_keys_bezier_loop(BeztEditData *bed, bActionGroup *agrp, BeztEd { FCurve *fcu; + /* sanity check */ + if (agrp == NULL) + return 0; + /* only iterate over the F-Curves that are in this group */ for (fcu= agrp->channels.first; fcu && fcu->grp==agrp; fcu= fcu->next) { if (ANIM_fcurve_keys_bezier_loop(bed, fcu, bezt_ok, bezt_cb, fcu_cb)) @@ -142,6 +146,10 @@ static short act_keys_bezier_loop(BeztEditData *bed, bAction *act, BeztEditFunc { FCurve *fcu; + /* sanity check */ + if (act == NULL) + return 0; + /* just loop through all F-Curves */ for (fcu= act->curves.first; fcu; fcu= fcu->next) { if (ANIM_fcurve_keys_bezier_loop(bed, fcu, bezt_ok, bezt_cb, fcu_cb)) @@ -154,6 +162,10 @@ static short act_keys_bezier_loop(BeztEditData *bed, bAction *act, BeztEditFunc /* This function is used to loop over the keyframe data of an AnimData block */ static short adt_keys_bezier_loop(BeztEditData *bed, AnimData *adt, BeztEditFunc bezt_ok, BeztEditFunc bezt_cb, FcuEditFunc fcu_cb, int filterflag) { + /* sanity check */ + if (adt == NULL) + return 0; + /* drivers or actions? */ if (filterflag & ADS_FILTER_ONLYDRIVERS) { FCurve *fcu; @@ -178,6 +190,10 @@ static short ob_keys_bezier_loop(BeztEditData *bed, Object *ob, BeztEditFunc bez { Key *key= ob_get_key(ob); + /* sanity check */ + if (ob == NULL) + return 0; + /* firstly, Object's own AnimData */ if (ob->adt) adt_keys_bezier_loop(bed, ob->adt, bezt_ok, bezt_cb, fcu_cb, filterflag); @@ -194,7 +210,11 @@ static short ob_keys_bezier_loop(BeztEditData *bed, Object *ob, BeztEditFunc bez /* This function is used to loop over the keyframe data in a Scene */ static short scene_keys_bezier_loop(BeztEditData *bed, Scene *sce, BeztEditFunc bezt_ok, BeztEditFunc bezt_cb, FcuEditFunc fcu_cb, int filterflag) { - World *wo= sce->world; + World *wo= (sce) ? sce->world : NULL; + + /* sanity check */ + if (sce == NULL) + return 0; /* Scene's own animation */ if (sce->adt) @@ -231,7 +251,7 @@ short ANIM_animchannel_keys_bezier_loop(BeztEditData *bed, bAnimListElem *ale, B return act_keys_bezier_loop(bed, (bAction *)ale->data, bezt_ok, bezt_cb, fcu_cb); case ALE_OB: /* object */ - return ob_keys_bezier_loop(bed, (Object *)ale->data, bezt_ok, bezt_cb, fcu_cb, filterflag); + return ob_keys_bezier_loop(bed, (Object *)ale->key_data, bezt_ok, bezt_cb, fcu_cb, filterflag); case ALE_SCE: /* scene */ return scene_keys_bezier_loop(bed, (Scene *)ale->data, bezt_ok, bezt_cb, fcu_cb, filterflag); } diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c index d8ed3fd1068..826728e83f9 100644 --- a/source/blender/editors/space_action/action_select.c +++ b/source/blender/editors/space_action/action_select.c @@ -858,17 +858,19 @@ static void mouse_action_keys (bAnimContext *ac, int mval[2], short select_mode, ANIM_deselect_anim_channels(ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR); /* Highlight Action-Group or F-Curve? */ - if (ale->type == ANIMTYPE_GROUP) { - bActionGroup *agrp= ale->data; - - agrp->flag |= AGRP_SELECTED; - ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, agrp, ANIMTYPE_GROUP); - } - else if (ale->type == ANIMTYPE_FCURVE) { - FCurve *fcu= ale->data; - - fcu->flag |= FCURVE_SELECTED; - ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ANIMTYPE_FCURVE); + if (ale && ale->data) { + if (ale->type == ANIMTYPE_GROUP) { + bActionGroup *agrp= ale->data; + + agrp->flag |= AGRP_SELECTED; + ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, agrp, ANIMTYPE_GROUP); + } + else if (ale->type == ANIMTYPE_FCURVE) { + FCurve *fcu= ale->data; + + fcu->flag |= FCURVE_SELECTED; + ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ANIMTYPE_FCURVE); + } } } else if (ac->datatype == ANIMCONT_GPENCIL) { @@ -881,7 +883,7 @@ static void mouse_action_keys (bAnimContext *ac, int mval[2], short select_mode, } /* only select keyframes if we clicked on a valid channel and hit something */ - if (ale) { + if (ale && found) { /* apply selection to keyframes */ if (/*gpl*/0) { /* grease pencil */ From 74884754d221a97c487d4c3630ceb4412b726863 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 12 Jun 2009 06:44:49 +0000 Subject: [PATCH 040/114] NLA SoC: Added menus including the operators coded already --- source/blender/editors/space_nla/nla_header.c | 108 ++++++++++++++---- source/blender/makesdna/DNA_space_types.h | 3 + source/blender/makesrna/RNA_access.h | 1 + source/blender/makesrna/intern/rna_space.c | 28 ++++- 4 files changed, 112 insertions(+), 28 deletions(-) diff --git a/source/blender/editors/space_nla/nla_header.c b/source/blender/editors/space_nla/nla_header.c index 7ce7536878b..0d42c544a3f 100644 --- a/source/blender/editors/space_nla/nla_header.c +++ b/source/blender/editors/space_nla/nla_header.c @@ -57,6 +57,9 @@ #include "ED_screen.h" #include "BIF_gl.h" +#include "BIF_transform.h" + +#include "RNA_access.h" #include "WM_api.h" #include "WM_types.h" @@ -74,37 +77,84 @@ enum { /* ************************ header area region *********************** */ -static void do_viewmenu(bContext *C, void *arg, int event) + +static void nla_viewmenu(bContext *C, uiLayout *layout, void *arg_unused) { + bScreen *sc= CTX_wm_screen(C); + ScrArea *sa= CTX_wm_area(C); + Scene *scene= CTX_data_scene(C); + SpaceNla *snla= (SpaceNla*)CTX_wm_space_data(C); + PointerRNA spaceptr; + /* retrieve state */ + RNA_pointer_create(&sc->id, &RNA_SpaceNLA, snla, &spaceptr); + + /* create menu */ + uiItemO(layout, NULL, ICON_MENU_PANEL, "NLAEDIT_OT_properties"); + + uiItemS(layout); + + uiItemR(layout, NULL, 0, &spaceptr, "show_cframe_indicator", 0, 0, 0); + + if (snla->flag & SNLA_DRAWTIME) + uiItemO(layout, "Show Frames", 0, "ANIM_OT_time_toggle"); + else + uiItemO(layout, "Show Seconds", 0, "ANIM_OT_time_toggle"); + + uiItemS(layout); + + if (scene->flag & SCE_NLA_EDIT_ON) + uiItemO(layout, NULL, 0, "NLAEDIT_OT_tweakmode_exit"); + else + uiItemO(layout, NULL, 0, "NLAEDIT_OT_tweakmode_enter"); + + uiItemS(layout); + + uiItemO(layout, NULL, 0, "NLA_OT_view_all"); + + if (sa->full) + uiItemO(layout, NULL, 0, "SCREEN_OT_screen_full_area"); // "Tile Window", Ctrl UpArrow + else + uiItemO(layout, NULL, 0, "SCREEN_OT_screen_full_area"); // "Maximize Window", Ctr DownArrow } -static uiBlock *dummy_viewmenu(bContext *C, ARegion *ar, void *arg_unused) +static void nla_selectmenu(bContext *C, uiLayout *layout, void *arg_unused) { - ScrArea *curarea= CTX_wm_area(C); - uiBlock *block; - short yco= 0, menuwidth=120; + uiItemO(layout, NULL, 0, "NLAEDIT_OT_select_all_toggle"); + uiItemBooleanO(layout, "Invert All", 0, "NLAEDIT_OT_select_all_toggle", "invert", 1); - block= uiBeginBlock(C, ar, "dummy_viewmenu", UI_EMBOSSP); - uiBlockSetButmFunc(block, do_viewmenu, NULL); + uiItemS(layout); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Nothing yet", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 1, 3, ""); - - if(curarea->headertype==HEADERTOP) { - uiBlockSetDirection(block, UI_DOWN); - } - else { - uiBlockSetDirection(block, UI_TOP); - uiBlockFlipOrder(block); - } - - uiTextBoundsBlock(block, 50); - uiEndBlock(C, block); - - return block; + uiItemO(layout, NULL, 0, "NLAEDIT_OT_select_border"); + uiItemBooleanO(layout, "Border Axis Range", 0, "NLAEDIT_OT_select_border", "axis_range", 1); } +static void nla_edit_transformmenu(bContext *C, uiLayout *layout, void *arg_unused) +{ + // XXX these operators may change for NLA... + uiItemEnumO(layout, "Grab/Move", 0, "TFM_OT_transform", "mode", TFM_TIME_TRANSLATE); + uiItemEnumO(layout, "Extend", 0, "TFM_OT_transform", "mode", TFM_TIME_EXTEND); + uiItemEnumO(layout, "Scale", 0, "TFM_OT_transform", "mode", TFM_TIME_SCALE); +} + +static void nla_editmenu(bContext *C, uiLayout *layout, void *arg_unused) +{ + uiItemMenuF(layout, "Transform", 0, nla_edit_transformmenu); + + uiItemS(layout); + + uiItemO(layout, NULL, 0, "NLA_OT_add_tracks"); + uiItemBooleanO(layout, "Add Tracks Above Selected", 0, "NLA_OT_add_tracks", "above_selected", 1); + + uiItemO(layout, NULL, 0, "NLAEDIT_OT_split"); + + uiItemS(layout); + + uiItemO(layout, NULL, 0, "NLAEDIT_OT_delete"); +} + +/* ------------------ */ + static void do_nla_buttons(bContext *C, void *arg, int event) { switch (event) { @@ -132,9 +182,17 @@ void nla_header_buttons(const bContext *C, ARegion *ar) int xmax; xmax= GetButStringLength("View"); - uiDefPulldownBut(block, dummy_viewmenu, CTX_wm_area(C), - "View", xco, yco-2, xmax-3, 24, ""); - xco+=XIC+xmax; + uiDefMenuBut(block, nla_viewmenu, NULL, "View", xco, yco, xmax-3, 20, ""); + xco+= xmax; + + xmax= GetButStringLength("Select"); + uiDefMenuBut(block, nla_selectmenu, NULL, "Select", xco, yco, xmax-3, 20, ""); + xco+= xmax; + + xmax= GetButStringLength("Edit"); + uiDefMenuBut(block, nla_editmenu, NULL, "Edit", xco, yco, xmax-3, 20, ""); + xco+= xmax; + } uiBlockSetEmboss(block, UI_EMBOSS); diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index c7abd8f7f83..3740633b576 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -696,8 +696,11 @@ enum { #define IMS_INFILESLI 4 /* nla->flag */ + // depreceated #define SNLA_ALLKEYED (1<<0) + // depreceated #define SNLA_ACTIVELAYERS (1<<1) + #define SNLA_DRAWTIME (1<<2) #define SNLA_NOTRANSKEYCULL (1<<3) #define SNLA_NODRAWCFRANUM (1<<4) diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 1a8bf88d1cc..d1fd3d78074 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -365,6 +365,7 @@ extern StructRNA RNA_Space; extern StructRNA RNA_Space3DView; extern StructRNA RNA_SpaceButtonsWindow; extern StructRNA RNA_SpaceImageEditor; +extern StructRNA RNA_SpaceNLA; extern StructRNA RNA_SpaceOutliner; extern StructRNA RNA_SpaceSequenceEditor; extern StructRNA RNA_SpaceTextEditor; diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 5de80cce2b5..1b776b727ce 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -92,10 +92,10 @@ static StructRNA* rna_Space_refine(struct PointerRNA *ptr) /*case SPACE_SOUND: return &RNA_SpaceAudioWindow; case SPACE_ACTION: - return &RNA_SpaceDopeSheetEditor; + return &RNA_SpaceDopeSheetEditor;*/ case SPACE_NLA: - return &RNA_SpaceNLAEditor; - case SPACE_SCRIPT: + return &RNA_SpaceNLA; + /*case SPACE_SCRIPT: return &RNA_SpaceScriptsWindow; case SPACE_TIME: return &RNA_SpaceTimeline; @@ -757,6 +757,27 @@ static void rna_def_space_text(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Replace Text", "Text to replace selected text with using the replace tool."); } +static void rna_def_space_nla(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna= RNA_def_struct(brna, "SpaceNLA", "Space"); + RNA_def_struct_sdna(srna, "SpaceNla"); + RNA_def_struct_ui_text(srna, "Space Nla Editor", "NLA editor space data."); + + /* display */ + prop= RNA_def_property(srna, "show_seconds", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SNLA_DRAWTIME); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); // XXX for now, only set with operator + RNA_def_property_ui_text(prop, "Show Seconds", "Show timing in seconds not frames."); + + prop= RNA_def_property(srna, "show_cframe_indicator", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SNLA_NODRAWCFRANUM); + RNA_def_property_ui_text(prop, "Show Frame Number Indicator", "Show frame number beside the current frame indicator line."); + +} + void RNA_def_space(BlenderRNA *brna) { rna_def_space(brna); @@ -767,6 +788,7 @@ void RNA_def_space(BlenderRNA *brna) rna_def_background_image(brna); rna_def_space_3dview(brna); rna_def_space_buttons(brna); + rna_def_space_nla(brna); } #endif From a87bc73d321f5bddc17fb5c6332637738bfb7fa6 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 19 Jun 2009 04:45:56 +0000 Subject: [PATCH 041/114] NLA SoC: Transition Strips + Strip Adding Operators + Bugfixes == Transitions == Transition strips are now able to be created + evaluated. Transitions allow for interpolation between the endpoints of two adjacent strips in the same track (i.e. two strips which occur in the same track one after the other, but with a gap between them). - The current behaviour when only one endpoint affects some setting is non-optimal, since it appears somewhat inconsistently extend/replace values... - Transform code needs a few fixes still to deal with these == Strip Adding Operators == * New strips referencing Actions can be added using the Shift-A hotkey while in the strips-area. You must have a track selected first though. The new strip will get added, starting from the current frame, in the selected track(s) only if there is enough space to do so. Otherwise, the new strip gets added at the top of the stack in a new track. * New transition strips can be added with the Shift-T hotkey while in the strips area. You must have two adjacent strips selected for this to work. == New Backend Methods == * Recoded the strip/track adding API to be more flexible * Added a new method for testing whether F-Curve has any modifiers of with certain attributes. Will be used in a later bugfix... == Bugfixes == - Fixed bug with strip-blending which caused the blending modes to be useless. - NLA buttons now use proper poll callbacks instead of defining checks - Commented out missing operator in menus, silencing warnings in console - Removed obsolete/incorrect comments --- source/blender/blenkernel/BKE_fcurve.h | 2 + source/blender/blenkernel/BKE_nla.h | 2 + source/blender/blenkernel/intern/anim_sys.c | 156 +++++++++++- source/blender/blenkernel/intern/fcurve.c | 36 +++ source/blender/blenkernel/intern/nla.c | 72 +++--- .../blender/editors/space_nla/nla_buttons.c | 65 +++-- source/blender/editors/space_nla/nla_draw.c | 23 +- source/blender/editors/space_nla/nla_edit.c | 229 +++++++++++++++++- source/blender/editors/space_nla/nla_header.c | 5 +- source/blender/editors/space_nla/nla_intern.h | 3 + source/blender/editors/space_nla/nla_ops.c | 7 + 11 files changed, 536 insertions(+), 64 deletions(-) diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h index 7058b9d236a..af272e892f2 100644 --- a/source/blender/blenkernel/BKE_fcurve.h +++ b/source/blender/blenkernel/BKE_fcurve.h @@ -112,6 +112,8 @@ void fcurve_free_modifiers(struct FCurve *fcu); struct FModifier *fcurve_find_active_modifier(struct FCurve *fcu); void fcurve_set_active_modifier(struct FCurve *fcu, struct FModifier *fcm); +short fcurve_has_suitable_modifier(FCurve *fcu, int mtype, short acttype); + float evaluate_time_fmodifiers(ListBase *modifiers, struct FCurve *fcu, float cvalue, float evaltime); void evaluate_value_fmodifiers(ListBase *modifiers, struct FCurve *fcu, float *cvalue, float evaltime); diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index 078c1ba52bb..5200ca6d4d7 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -61,6 +61,8 @@ void BKE_nlatrack_solo_toggle(struct AnimData *adt, struct NlaTrack *nlt); short BKE_nlatrack_has_space(struct NlaTrack *nlt, float start, float end); void BKE_nlatrack_sort_strips(struct NlaTrack *nlt); +short BKE_nlatrack_add_strip(struct NlaTrack *nlt, struct NlaStrip *strip); + struct NlaStrip *BKE_nlastrip_find_active(struct NlaTrack *nlt); short BKE_nlastrip_within_bounds(struct NlaStrip *strip, float min, float max); diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index a864e3d4e87..2efb4f2b2d3 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -558,13 +558,20 @@ typedef struct NlaEvalStrip { short track_index; /* the index of the track within the list */ short strip_mode; /* which end of the strip are we looking at */ + + float strip_time; /* time at which which strip is being evaluated */ } NlaEvalStrip; /* NlaEvalStrip->strip_mode */ enum { + /* standard evaluation */ NES_TIME_BEFORE = -1, NES_TIME_WITHIN, NES_TIME_AFTER, + + /* transition-strip evaluations */ + NES_TIME_TRANSITION_START, + NES_TIME_TRANSITION_END, } eNlaEvalStrip_StripMode; @@ -583,10 +590,10 @@ typedef struct NlaEvalChannel { /* ---------------------- */ -/* non clipped mapping for strip-time <-> global time +/* non clipped mapping for strip-time <-> global time (for Action-Clips) * invert = convert action-strip time to global time */ -static float nlastrip_get_frame (NlaStrip *strip, float cframe, short invert) +static float nlastrip_get_frame_actionclip (NlaStrip *strip, float cframe, short invert) { float length, actlength, repeat, scale; @@ -603,8 +610,8 @@ static float nlastrip_get_frame (NlaStrip *strip, float cframe, short invert) if (IS_EQ(actlength, 0.0f)) actlength = 1.0f; /* length of strip */ - length = strip->end - strip->start; - if (IS_EQ(length, 0.0f)) length= actlength * scale * repeat; + length= actlength * scale * repeat; + if (IS_EQ(length, 0.0f)) length= strip->end - strip->start; /* reversed = play strip backwards */ if (strip->flag & NLASTRIP_FLAG_REVERSE) { @@ -623,6 +630,48 @@ static float nlastrip_get_frame (NlaStrip *strip, float cframe, short invert) } } +/* non clipped mapping for strip-time <-> global time (for Transitions) + * invert = convert action-strip time to global time + */ +static float nlastrip_get_frame_transition (NlaStrip *strip, float cframe, short invert) +{ + float length; + + /* length of strip */ + length= strip->end - strip->start; + + /* reversed = play strip backwards */ + if (strip->flag & NLASTRIP_FLAG_REVERSE) { + /* invert = convert within-strip-time to global time */ + if (invert) + return strip->end - (length * cframe); + else + return (strip->end - cframe) / length; + } + else { + /* invert = convert within-strip-time to global time */ + if (invert) + return (length * cframe) + strip->start; + else + return (cframe - strip->start) / length; + } +} + +/* non clipped mapping for strip-time <-> global time + * invert = convert action-strip time to global time + */ +static float nlastrip_get_frame (NlaStrip *strip, float cframe, short invert) +{ + switch (strip->type) { + case NLASTRIP_TYPE_TRANSITION: /* transition */ + return nlastrip_get_frame_transition(strip, cframe, invert); + + case NLASTRIP_TYPE_CLIP: /* action-clip (default) */ + default: + return nlastrip_get_frame_actionclip(strip, cframe, invert); + } +} + /* calculate influence of strip based for given frame based on blendin/out values */ static float nlastrip_get_influence (NlaStrip *strip, float cframe) { @@ -631,7 +680,6 @@ static float nlastrip_get_influence (NlaStrip *strip, float cframe) strip->blendout= (float)fabs(strip->blendout); /* result depends on where frame is in respect to blendin/out values */ - // the +0.0001 factors are to combat rounding errors if (IS_EQ(strip->blendin, 0)==0 && (cframe <= (strip->start + strip->blendin))) { /* there is some blend-in */ return (float)fabs(cframe - strip->start) / (strip->blendin); @@ -746,12 +794,13 @@ static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index * - negative influence is not supported yet... how would that be defined? */ // TODO: this sounds a bit hacky having a few isolated F-Curves stuck on some data it operates on... - // TODO: should we clamp the time to only be on the endpoints of the strip? nlastrip_evaluate_controls(estrip, ctime); if (estrip->influence <= 0.0f) // XXX is it useful to invert the strip? return; - /* check if strip has valid data to evaluate */ + /* check if strip has valid data to evaluate, + * and/or perform any additional type-specific actions + */ switch (estrip->type) { case NLASTRIP_TYPE_CLIP: /* clip must have some action to evaluate */ @@ -760,9 +809,12 @@ static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index break; case NLASTRIP_TYPE_TRANSITION: /* there must be strips to transition from and to (i.e. prev and next required) */ - // TODO: what happens about cross-track transitions? if (ELEM(NULL, estrip->prev, estrip->next)) return; + + /* evaluate controls for the relevant extents of the bordering strips... */ + nlastrip_evaluate_controls(estrip->prev, estrip->start); + nlastrip_evaluate_controls(estrip->next, estrip->end); break; } @@ -773,6 +825,7 @@ static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index nes->strip= estrip; nes->strip_mode= side; nes->track_index= index; + nes->strip_time= estrip->strip_time; BLI_addtail(list, nes); } @@ -847,6 +900,8 @@ static NlaEvalChannel *nlaevalchan_verify (PointerRNA *ptr, ListBase *channels, nec->prop= prop; nec->index= fcu->array_index; } + else + *newChan= 0; /* we can now return */ return nec; @@ -856,6 +911,7 @@ static NlaEvalChannel *nlaevalchan_verify (PointerRNA *ptr, ListBase *channels, static void nlaevalchan_accumulate (NlaEvalChannel *nec, NlaEvalStrip *nes, short newChan, float value) { NlaStrip *strip= nes->strip; + short blendmode= strip->blendmode; float inf= strip->influence; /* if channel is new, just store value regardless of blending factors, etc. */ @@ -863,13 +919,19 @@ static void nlaevalchan_accumulate (NlaEvalChannel *nec, NlaEvalStrip *nes, shor nec->value= value; return; } + + /* if this is being performed as part of transition evaluation, incorporate + * an additional weighting factor for the influence + */ + if (nes->strip_mode == NES_TIME_TRANSITION_END) + inf *= nes->strip_time; /* premultiply the value by the weighting factor */ if (IS_EQ(inf, 0)) return; value *= inf; /* perform blending */ - switch (strip->blendmode) { + switch (blendmode) { case NLASTRIP_MODE_ADD: /* simply add the scaled value on to the stack */ nec->value += value; @@ -938,8 +1000,80 @@ static void nlastrip_evaluate_actionclip (PointerRNA *ptr, ListBase *channels, N } } +/* evaluate transition strip */ +static void nlastrip_evaluate_transition (PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes) +{ + ListBase tmp_channels = {NULL, NULL}; + NlaEvalChannel *nec, *necn, *necd; + NlaEvalStrip tmp_nes; + NlaStrip *s1, *s2; + + /* get the two strips to operate on + * - we use the endpoints of the strips directly flanking our strip + * using these as the endpoints of the transition (destination and source) + * - these should have already been determined to be valid... + * - if this strip is being played in reverse, we need to swap these endpoints + * otherwise they will be interpolated wrong + */ + if (nes->strip->flag & NLASTRIP_FLAG_REVERSE) { + s1= nes->strip->next; + s2= nes->strip->prev; + } + else { + s1= nes->strip->prev; + s2= nes->strip->next; + } + + /* prepare template for 'evaluation strip' + * - based on the transition strip's evaluation strip data + * - strip_mode is NES_TIME_TRANSITION_* based on which endpoint + * - strip_time is the 'normalised' (i.e. in-strip) time for evaluation, + * which doubles up as an additional weighting factor for the strip influences + * which allows us to appear to be 'interpolating' between the two extremes + */ + tmp_nes= *nes; + + /* evaluate these strips into a temp-buffer (tmp_channels) */ + /* first strip */ + tmp_nes.strip_mode= NES_TIME_TRANSITION_START; + tmp_nes.strip= s1; + nlastrip_evaluate_actionclip(ptr, &tmp_channels, &tmp_nes); + + /* second strip */ + tmp_nes.strip_mode= NES_TIME_TRANSITION_END; + tmp_nes.strip= s2; + nlastrip_evaluate_actionclip(ptr, &tmp_channels, &tmp_nes); + + + /* optimise - abort if no channels */ + if (tmp_channels.first == NULL) + return; + + + /* accumulate results in tmp_channels buffer to the accumulation buffer */ + for (nec= tmp_channels.first; nec; nec= necn) { + /* get pointer to next channel in case we remove the current channel from the temp-buffer */ + necn= nec->next; + + /* try to find an existing matching channel for this setting in the accumulation buffer */ + necd= nlaevalchan_find_match(channels, &nec->ptr, nec->prop, nec->index); + + /* if there was a matching channel already in the buffer, accumulate to it, + * otherwise, add the current channel to the buffer for efficiency + */ + if (necd) + nlaevalchan_accumulate(necd, nes, 0, nec->value); + else { + BLI_remlink(&tmp_channels, nec); + BLI_addtail(channels, nec); + } + } + + /* free temp-channels that haven't been assimilated into the buffer */ + BLI_freelistN(&tmp_channels); +} + /* evaluates the given evaluation strip */ -// TODO: only evaluate here, but flush in one go using the accumulated channels at end... static void nlastrip_evaluate (PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes) { /* actions to take depend on the type of strip */ @@ -948,7 +1082,7 @@ static void nlastrip_evaluate (PointerRNA *ptr, ListBase *channels, NlaEvalStrip nlastrip_evaluate_actionclip(ptr, channels, nes); break; case NLASTRIP_TYPE_TRANSITION: /* transition */ - // XXX code this... + nlastrip_evaluate_transition(ptr, channels, nes); break; } } diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 5820761234c..d8b5135a1b1 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -2242,6 +2242,42 @@ void fcurve_set_active_modifier (FCurve *fcu, FModifier *fcm) fcm->flag |= FMODIFIER_FLAG_ACTIVE; } +/* Do we have any modifiers which match certain criteria + * - mtype - type of modifier (if 0, doesn't matter) + * - acttype - type of action to perform (if -1, doesn't matter) + */ +short fcurve_has_suitable_modifier (FCurve *fcu, int mtype, short acttype) +{ + FModifier *fcm; + + /* if there are no specific filtering criteria, just skip */ + if ((mtype == 0) && (acttype == 0)) + return (fcu && fcu->modifiers.first); + + /* sanity checks */ + if ELEM(NULL, fcu, fcu->modifiers.first) + return 0; + + /* find the first mdifier fitting these criteria */ + for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next) { + FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); + short mOk=1, aOk=1; /* by default 1, so that when only one test, won't fail */ + + /* check if applicable ones are fullfilled */ + if (mtype) + mOk= (fcm->type == mtype); + if (acttype > -1) + aOk= (fmi->acttype == acttype); + + /* if both are ok, we've found a hit */ + if (mOk && aOk) + return 1; + } + + /* no matches */ + return 0; +} + /* Evaluation API --------------------------- */ /* evaluate time modifications imposed by some F-Curve Modifiers diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index cef14128032..0684d943754 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -293,9 +293,8 @@ NlaStrip *add_nlastrip (bAction *act) /* Add new NLA-strip to the top of the NLA stack - i.e. into the last track if space, or a new one otherwise */ NlaStrip *add_nlastrip_to_stack (AnimData *adt, bAction *act) { - NlaStrip *strip, *ns; + NlaStrip *strip; NlaTrack *nlt; - short not_added = 1; /* sanity checks */ if ELEM(NULL, adt, act) @@ -306,35 +305,14 @@ NlaStrip *add_nlastrip_to_stack (AnimData *adt, bAction *act) if (strip == NULL) return NULL; - /* check if the last NLA-track (if it exists) has any space for this strip: - * - if so, add this strip to that track - */ - if ( (adt->nla_tracks.last == NULL) || - (BKE_nlatrack_has_space(adt->nla_tracks.last, strip->start, strip->end)==0) ) - { - /* no space, so add to a new track... */ + /* firstly try adding strip to last track, but if that fails, add to a new track */ + if (BKE_nlatrack_add_strip(adt->nla_tracks.last, strip) == 0) { + /* trying to add to the last track failed (no track or no space), + * so add a new track to the stack, and add to that... + */ nlt= add_nlatrack(adt, NULL); + BKE_nlatrack_add_strip(nlt, strip); } - else - { - /* there's some space, so add to this track... */ - nlt= adt->nla_tracks.last; - } - - /* find the right place to add the strip to the nominated track */ - for (ns= nlt->strips.first; ns; ns= ns->next) { - /* if current strip occurs after the new strip, add it before */ - if (ns->start > strip->end) { - BLI_insertlinkbefore(&nlt->strips, ns, strip); - not_added= 0; - break; - } - } - if (not_added) { - /* just add to the end of the list of the strips then... */ - BLI_addtail(&nlt->strips, strip); - } - /* returns the strip added */ return strip; @@ -490,6 +468,40 @@ void BKE_nlatrack_sort_strips (NlaTrack *nlt) nlt->strips.last= tmp.last; } +/* Add the given NLA-Strip to the given NLA-Track, assuming that it + * isn't currently attached to another one + */ +short BKE_nlatrack_add_strip (NlaTrack *nlt, NlaStrip *strip) +{ + NlaStrip *ns; + short not_added = 1; + + /* sanity checks */ + if ELEM(NULL, nlt, strip) + return 0; + + /* check if any space to add */ + if (BKE_nlatrack_has_space(nlt, strip->start, strip->end)==0) + return 0; + + /* find the right place to add the strip to the nominated track */ + for (ns= nlt->strips.first; ns; ns= ns->next) { + /* if current strip occurs after the new strip, add it before */ + if (ns->start > strip->end) { + BLI_insertlinkbefore(&nlt->strips, ns, strip); + not_added= 0; + break; + } + } + if (not_added) { + /* just add to the end of the list of the strips then... */ + BLI_addtail(&nlt->strips, strip); + } + + /* added... */ + return 1; +} + /* NLA Strips -------------------------------------- */ /* Find the active NLA-strip within the given track */ @@ -571,7 +583,7 @@ short nlastrip_is_first (AnimData *adt, NlaStrip *strip) /* should be first now */ return 1; } - + /* Tools ------------------------------------------- */ /* For the given AnimData block, add the active action to the NLA diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c index cb21dd66934..cb76f7fc735 100644 --- a/source/blender/editors/space_nla/nla_buttons.c +++ b/source/blender/editors/space_nla/nla_buttons.c @@ -144,11 +144,38 @@ static int nla_panel_context(const bContext *C, PointerRNA *nlt_ptr, PointerRNA return found; } +#if 0 static int nla_panel_poll(const bContext *C, PanelType *pt) { return nla_panel_context(C, NULL, NULL); } +#endif +static int nla_track_panel_poll(const bContext *C, PanelType *pt) +{ + PointerRNA ptr; + return (nla_panel_context(C, &ptr, NULL) && (ptr.data != NULL)); +} + +static int nla_strip_panel_poll(const bContext *C, PanelType *pt) +{ + PointerRNA ptr; + return (nla_panel_context(C, NULL, &ptr) && (ptr.data != NULL)); +} + +static int nla_strip_actclip_panel_poll(const bContext *C, PanelType *pt) +{ + PointerRNA ptr; + NlaStrip *strip; + + if (!nla_panel_context(C, NULL, &ptr)) + return 0; + if (ptr.data == NULL) + return 0; + + strip= ptr.data; + return (strip->type == NLASTRIP_TYPE_CLIP); +} /* -------------- */ @@ -163,8 +190,6 @@ static void nla_panel_track (const bContext *C, Panel *pa) /* check context and also validity of pointer */ if (!nla_panel_context(C, &nlt_ptr, NULL)) return; - if (nlt_ptr.data == NULL) - return; block= uiLayoutGetBlock(layout); uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL); @@ -185,8 +210,6 @@ static void nla_panel_properties(const bContext *C, Panel *pa) /* check context and also validity of pointer */ if (!nla_panel_context(C, NULL, &strip_ptr)) return; - if (strip_ptr.data == NULL) - return; block= uiLayoutGetBlock(layout); uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL); @@ -239,8 +262,6 @@ static void nla_panel_actclip(const bContext *C, Panel *pa) /* check context and also validity of pointer */ if (!nla_panel_context(C, NULL, &strip_ptr)) return; - if (strip_ptr.data == NULL) - return; // XXX FIXME: move this check into a poll callback if (RNA_enum_get(&strip_ptr, "type") != NLASTRIP_TYPE_CLIP) @@ -279,8 +300,6 @@ static void nla_panel_evaluation(const bContext *C, Panel *pa) /* check context and also validity of pointer */ if (!nla_panel_context(C, NULL, &strip_ptr)) return; - if (strip_ptr.data == NULL) - return; block= uiLayoutGetBlock(layout); uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL); @@ -291,6 +310,24 @@ static void nla_panel_evaluation(const bContext *C, Panel *pa) // animated_time } +/* F-Modifiers for active NLA-Strip */ +static void nla_panel_modifiers(const bContext *C, Panel *pa) +{ + PointerRNA strip_ptr; + uiLayout *layout= pa->layout; + //uiLayout *column, *row, *subcol; + uiBlock *block; + + /* check context and also validity of pointer */ + if (!nla_panel_context(C, NULL, &strip_ptr)) + return; + + block= uiLayoutGetBlock(layout); + uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL); + + // TODO... +} + /* ******************* general ******************************** */ @@ -302,35 +339,35 @@ void nla_buttons_register(ARegionType *art) strcpy(pt->idname, "NLA_PT_track"); strcpy(pt->label, "Active Track"); pt->draw= nla_panel_track; - pt->poll= nla_panel_poll; + pt->poll= nla_track_panel_poll; BLI_addtail(&art->paneltypes, pt); pt= MEM_callocN(sizeof(PanelType), "spacetype nla panel properties"); strcpy(pt->idname, "NLA_PT_properties"); strcpy(pt->label, "Active Strip"); pt->draw= nla_panel_properties; - pt->poll= nla_panel_poll; + pt->poll= nla_strip_panel_poll; BLI_addtail(&art->paneltypes, pt); pt= MEM_callocN(sizeof(PanelType), "spacetype nla panel properties"); strcpy(pt->idname, "NLA_PT_actionclip"); strcpy(pt->label, "Action Clip"); pt->draw= nla_panel_actclip; - pt->poll= nla_panel_poll; // XXX need a special one to check for 'action clip' types only + pt->poll= nla_strip_actclip_panel_poll; BLI_addtail(&art->paneltypes, pt); pt= MEM_callocN(sizeof(PanelType), "spacetype nla panel evaluation"); strcpy(pt->idname, "NLA_PT_evaluation"); strcpy(pt->label, "Evaluation"); pt->draw= nla_panel_evaluation; - pt->poll= nla_panel_poll; + pt->poll= nla_strip_panel_poll; BLI_addtail(&art->paneltypes, pt); pt= MEM_callocN(sizeof(PanelType), "spacetype nla panel modifiers"); strcpy(pt->idname, "NLA_PT_modifiers"); strcpy(pt->label, "Modifiers"); - //pt->draw= nla_panel_modifiers; - pt->poll= nla_panel_poll; + pt->draw= nla_panel_modifiers; + pt->poll= nla_strip_panel_poll; BLI_addtail(&art->paneltypes, pt); } diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index 8d417a150aa..3a3f86bb5a3 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -202,11 +202,20 @@ static void nla_draw_strip_text (NlaTrack *nlt, NlaStrip *strip, int index, View char str[256]; rctf rect; - /* for now, just init the string with a fixed-format */ - if (strip->act) - sprintf(str, "%d | Act: %s | %.2f <-> %.2f", index, strip->act->id.name+2, strip->start, strip->end); - else - sprintf(str, "%d | Act: ", index); + /* for now, just init the string with fixed-formats */ + switch (strip->type) { + case NLASTRIP_TYPE_TRANSITION: /* Transition */ + sprintf(str, "%d | Transition | %.2f <-> %.2f", index, strip->start, strip->end); + break; + + case NLASTRIP_TYPE_CLIP: /* Action-Clip (default) */ + default: + if (strip->act) + sprintf(str, "%d | Act: %s | %.2f <-> %.2f", index, strip->act->id.name+2, strip->start, strip->end); + else + sprintf(str, "%d | Act: ", index); // xxx... need a better format? + break; + } /* set text colour - if colours (see above) are light, draw black text, otherwise draw white */ if (strip->flag & (NLASTRIP_FLAG_ACTIVE|NLASTRIP_FLAG_SELECT|NLASTRIP_FLAG_TWEAKUSER)) @@ -295,7 +304,9 @@ void draw_nla_main_data (bAnimContext *ac, SpaceNla *snla, ARegion *ar) { AnimData *adt= BKE_animdata_from_id(ale->id); - /* just draw a semi-shaded rect spanning the width of the viewable area if there's data */ + /* just draw a semi-shaded rect spanning the width of the viewable area if there's data, + * and a second darker rect within which we draw keyframe indicator dots if there's data + */ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index e8af67aebd1..2996a005177 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -48,6 +48,8 @@ #include "BKE_animsys.h" #include "BKE_nla.h" #include "BKE_context.h" +#include "BKE_library.h" +#include "BKE_main.h" #include "BKE_report.h" #include "BKE_screen.h" #include "BKE_utildefines.h" @@ -215,6 +217,229 @@ void NLAEDIT_OT_tweakmode_exit (wmOperatorType *ot) /* *********************************************** */ /* NLA Editing Operations */ +/* ******************** Add Action-Clip Operator ***************************** */ +/* Add a new Action-Clip strip to the active track (or the active block if no space in the track) */ + +/* pop up menu allowing user to choose the action to use */ +static int nlaedit_add_actionclip_invoke (bContext *C, wmOperator *op, wmEvent *evt) +{ + Main *m= CTX_data_main(C); + bAction *act; + uiPopupMenu *pup; + uiLayout *layout; + + pup= uiPupMenuBegin(C, "Add Action Clip", 0); + layout= uiPupMenuLayout(pup); + + /* loop through Actions in Main database, adding as items in the menu */ + for (act= m->action.first; act; act= act->id.next) + uiItemStringO(layout, act->id.name+2, 0, "NLAEDIT_OT_add_actionclip", "action", act->id.name); + uiItemS(layout); + + uiPupMenuEnd(C, pup); + + return OPERATOR_CANCELLED; +} + +/* add the specified action as new strip */ +static int nlaedit_add_actionclip_exec (bContext *C, wmOperator *op) +{ + bAnimContext ac; + Scene *scene; + + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter, items; + + bAction *act = NULL; + char actname[22]; + float cfra; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + scene= ac.scene; + cfra= (float)CFRA; + + /* get action to use */ + RNA_string_get(op->ptr, "action", actname); + act= (bAction *)find_id("AC", actname+2); + + if (act == NULL) { + BKE_report(op->reports, RPT_ERROR, "No valid Action to add."); + //printf("Add strip - actname = '%s' \n", actname); + return OPERATOR_CANCELLED; + } + + /* get a list of the editable tracks being shown in the NLA + * - this is limited to active ones for now, but could be expanded to + */ + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_ACTIVE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT); + items= ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + if (items == 0) { + BKE_report(op->reports, RPT_ERROR, "No active track(s) to add strip to."); + return OPERATOR_CANCELLED; + } + + /* for every active track, try to add strip to free space in track or to the top of the stack if no space */ + for (ale= anim_data.first; ale; ale= ale->next) { + NlaTrack *nlt= (NlaTrack *)ale->data; + AnimData *adt= BKE_animdata_from_id(ale->id); + NlaStrip *strip= NULL; + + /* create a new strip, and offset it to start on the current frame */ + strip= add_nlastrip(act); + + strip->end += (cfra - strip->start); + strip->start = cfra; + + /* firstly try adding strip to our current track, but if that fails, add to a new track */ + if (BKE_nlatrack_add_strip(nlt, strip) == 0) { + /* trying to add to the current failed (no space), + * so add a new track to the stack, and add to that... + */ + nlt= add_nlatrack(adt, NULL); + BKE_nlatrack_add_strip(nlt, strip); + } + } + + /* free temp data */ + BLI_freelistN(&anim_data); + + /* set notifier that things have changed */ + ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); + WM_event_add_notifier(C, NC_SCENE, NULL); + + /* done */ + return OPERATOR_FINISHED; +} + +void NLAEDIT_OT_add_actionclip (wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Add Action Strip"; + ot->idname= "NLAEDIT_OT_add_actionclip"; + ot->description= "Add an Action-Clip strip (i.e. an NLA Strip referencing an Action) to the active track."; + + /* api callbacks */ + ot->invoke= nlaedit_add_actionclip_invoke; + ot->exec= nlaedit_add_actionclip_exec; + ot->poll= nlaop_poll_tweakmode_off; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* props */ + // TODO: this would be nicer as an ID-pointer... + RNA_def_string(ot->srna, "action", "", 21, "Action", "Name of Action to add as a new Action-Clip Strip."); +} + +/* ******************** Add Transition Operator ***************************** */ +/* Add a new transition strip between selected strips */ + +/* add the specified action as new strip */ +static int nlaedit_add_transition_exec (bContext *C, wmOperator *op) +{ + bAnimContext ac; + + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + int done = 0; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* get a list of the editable tracks being shown in the NLA */ + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* for each track, find pairs of strips to add transitions to */ + for (ale= anim_data.first; ale; ale= ale->next) { + NlaTrack *nlt= (NlaTrack *)ale->data; + NlaStrip *s1, *s2; + + /* get initial pair of strips */ + if ELEM(nlt->strips.first, NULL, nlt->strips.last) + continue; + s1= nlt->strips.first; + s2= s1->next; + + /* loop over strips */ + for (; s1 && s2; s1=s2, s2=s2->next) { + NlaStrip *strip; + + /* check if both are selected */ + if ELEM(0, (s1->flag & NLASTRIP_FLAG_SELECT), (s2->flag & NLASTRIP_FLAG_SELECT)) + continue; + /* check if there's space between the two */ + if (IS_EQ(s1->end, s2->start)) + continue; + + /* allocate new strip */ + strip= MEM_callocN(sizeof(NlaStrip), "NlaStrip"); + BLI_insertlinkafter(&nlt->strips, s1, strip); + + /* set the type */ + strip->type= NLASTRIP_TYPE_TRANSITION; + + /* generic settings + * - selected flag to highlight this to the user + * - auto-blends to ensure that blend in/out values are automatically + * determined by overlaps of strips + */ + strip->flag = NLASTRIP_FLAG_SELECT|NLASTRIP_FLAG_AUTO_BLENDS; + + /* range is simply defined as the endpoints of the adjacent strips */ + strip->start = s1->end; + strip->end = s2->start; + + /* scale and repeat aren't of any use, but shouldn't ever be 0 */ + strip->scale= 1.0f; + strip->repeat = 1.0f; + + /* make note of this */ + done++; + } + } + + /* free temp data */ + BLI_freelistN(&anim_data); + + /* was anything added? */ + if (done) { + /* set notifier that things have changed */ + ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); + WM_event_add_notifier(C, NC_SCENE, NULL); + + /* done */ + return OPERATOR_FINISHED; + } + else { + BKE_report(op->reports, RPT_ERROR, "Needs at least a pair of adjacent selected strips."); + return OPERATOR_CANCELLED; + } +} + +void NLAEDIT_OT_add_transition (wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Add Transition"; + ot->idname= "NLAEDIT_OT_add_transition"; + ot->description= "Add a transition strip between two adjacent selected strips."; + + /* api callbacks */ + ot->exec= nlaedit_add_transition_exec; + ot->poll= nlaop_poll_tweakmode_off; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + /* ******************** Delete Strips Operator ***************************** */ /* Deletes the selected NLA-Strips */ @@ -230,7 +455,7 @@ static int nlaedit_delete_exec (bContext *C, wmOperator *op) if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; - /* get a list of the AnimData blocks being shown in the NLA */ + /* get a list of the editable tracks being shown in the NLA */ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT); ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); @@ -292,7 +517,7 @@ static int nlaedit_split_exec (bContext *C, wmOperator *op) if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; - /* get a list of the AnimData blocks being shown in the NLA */ + /* get a list of editable tracks being shown in the NLA */ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT); ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); diff --git a/source/blender/editors/space_nla/nla_header.c b/source/blender/editors/space_nla/nla_header.c index 0d42c544a3f..970d602c0af 100644 --- a/source/blender/editors/space_nla/nla_header.c +++ b/source/blender/editors/space_nla/nla_header.c @@ -110,7 +110,7 @@ static void nla_viewmenu(bContext *C, uiLayout *layout, void *arg_unused) uiItemS(layout); - uiItemO(layout, NULL, 0, "NLA_OT_view_all"); + //uiItemO(layout, NULL, 0, "NLA_OT_view_all"); if (sa->full) uiItemO(layout, NULL, 0, "SCREEN_OT_screen_full_area"); // "Tile Window", Ctrl UpArrow @@ -146,6 +146,9 @@ static void nla_editmenu(bContext *C, uiLayout *layout, void *arg_unused) uiItemO(layout, NULL, 0, "NLA_OT_add_tracks"); uiItemBooleanO(layout, "Add Tracks Above Selected", 0, "NLA_OT_add_tracks", "above_selected", 1); + uiItemO(layout, NULL, 0, "NLA_OT_add_actionclip"); + uiItemO(layout, NULL, 0, "NLA_OT_add_transition"); + uiItemO(layout, NULL, 0, "NLAEDIT_OT_split"); uiItemS(layout); diff --git a/source/blender/editors/space_nla/nla_intern.h b/source/blender/editors/space_nla/nla_intern.h index 5c6670cfd6f..f1bde40f4ab 100644 --- a/source/blender/editors/space_nla/nla_intern.h +++ b/source/blender/editors/space_nla/nla_intern.h @@ -92,6 +92,9 @@ void NLAEDIT_OT_tweakmode_exit(wmOperatorType *ot); /* --- */ +void NLAEDIT_OT_add_actionclip(wmOperatorType *ot); +void NLAEDIT_OT_add_transition(wmOperatorType *ot); + void NLAEDIT_OT_delete(wmOperatorType *ot); void NLAEDIT_OT_split(wmOperatorType *ot); diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c index 981ef9a4f87..a9b7022157e 100644 --- a/source/blender/editors/space_nla/nla_ops.c +++ b/source/blender/editors/space_nla/nla_ops.c @@ -134,6 +134,9 @@ void nla_operatortypes(void) WM_operatortype_append(NLAEDIT_OT_tweakmode_enter); WM_operatortype_append(NLAEDIT_OT_tweakmode_exit); + WM_operatortype_append(NLAEDIT_OT_add_actionclip); + WM_operatortype_append(NLAEDIT_OT_add_transition); + WM_operatortype_append(NLAEDIT_OT_delete); WM_operatortype_append(NLAEDIT_OT_split); } @@ -208,6 +211,10 @@ static void nla_keymap_main (wmWindowManager *wm, ListBase *keymap) WM_keymap_add_item(keymap, "NLAEDIT_OT_tweakmode_enter", TABKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "NLAEDIT_OT_tweakmode_exit", TABKEY, KM_PRESS, 0, 0); + /* add strips */ + WM_keymap_add_item(keymap, "NLAEDIT_OT_add_actionclip", AKEY, KM_PRESS, KM_SHIFT, 0); + WM_keymap_add_item(keymap, "NLAEDIT_OT_add_transition", TKEY, KM_PRESS, KM_SHIFT, 0); + /* delete */ WM_keymap_add_item(keymap, "NLAEDIT_OT_delete", XKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "NLAEDIT_OT_delete", DELKEY, KM_PRESS, 0, 0); From 8ffb1dacad032e42830debe9b51fdd961def354f Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 19 Jun 2009 04:58:40 +0000 Subject: [PATCH 042/114] NLA SoC: Bugfix for Deleting Keyframes When an F-Curve doesn't contain any keyframes anymore but it still exists, the F-Curve's value is not recalculated and flushed anymore if the F-Curve's value will not change. That is, if the F-Curve doesn't have any other data, i.e. drivers or generator-modifiers, which would still change its value, it wouldn't be recalculated to have a value of zero. This solves the problem of deleting all scale keyframes, whereby objects/bones would appear to 'vanish' --- source/blender/blenkernel/BKE_fcurve.h | 2 +- source/blender/blenkernel/intern/fcurve.c | 12 +++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h index af272e892f2..5c77e3c2ae4 100644 --- a/source/blender/blenkernel/BKE_fcurve.h +++ b/source/blender/blenkernel/BKE_fcurve.h @@ -112,7 +112,7 @@ void fcurve_free_modifiers(struct FCurve *fcu); struct FModifier *fcurve_find_active_modifier(struct FCurve *fcu); void fcurve_set_active_modifier(struct FCurve *fcu, struct FModifier *fcm); -short fcurve_has_suitable_modifier(FCurve *fcu, int mtype, short acttype); +short fcurve_has_suitable_modifier(struct FCurve *fcu, int mtype, short acttype); float evaluate_time_fmodifiers(ListBase *modifiers, struct FCurve *fcu, float cvalue, float evaltime); void evaluate_value_fmodifiers(ListBase *modifiers, struct FCurve *fcu, float *cvalue, float evaltime); diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index d8b5135a1b1..856930e5a44 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -2415,10 +2415,16 @@ float evaluate_fcurve (FCurve *fcu, float evaltime) } /* Calculate the value of the given F-Curve at the given frame, and set its curval */ -// TODO: will this be necessary? void calculate_fcurve (FCurve *fcu, float ctime) { - /* calculate and set curval (evaluates driver too) */ - fcu->curval= evaluate_fcurve(fcu, ctime); + /* only calculate + set curval (overriding the existing value) if curve has + * any data which warrants this... + */ + if ( (fcu->totvert) || (fcu->driver && !(fcu->driver->flag & DRIVER_FLAG_INVALID)) || + fcurve_has_suitable_modifier(fcu, 0, FMI_TYPE_GENERATE_CURVE) ) + { + /* calculate and set curval (evaluates driver too if necessary) */ + fcu->curval= evaluate_fcurve(fcu, ctime); + } } From e3fc5481b9da35336e5f7b7413938a089eb384af Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 19 Jun 2009 11:56:53 +0000 Subject: [PATCH 043/114] NLA SoC: Bugfixes * Loading old Action Editors resulted in wrong view settings being used * Wrong operator names used in previous commit... --- source/blender/blenloader/intern/readfile.c | 2 +- source/blender/editors/space_nla/nla_header.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index fe19496bd38..31f97e1d41d 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -5755,7 +5755,7 @@ static void area_add_window_regions(ScrArea *sa, SpaceLink *sl, ListBase *lb) ar->v2d.scroll = (V2D_SCROLL_BOTTOM|V2D_SCROLL_SCALE_HORIZONTAL); ar->v2d.scroll |= (V2D_SCROLL_RIGHT); ar->v2d.keepzoom= V2D_LOCKZOOM_Y; - ar->v2d.align= V2D_ALIGN_NO_NEG_Y; + ar->v2d.align= V2D_ALIGN_NO_POS_Y; ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL; break; } diff --git a/source/blender/editors/space_nla/nla_header.c b/source/blender/editors/space_nla/nla_header.c index 970d602c0af..175f40befeb 100644 --- a/source/blender/editors/space_nla/nla_header.c +++ b/source/blender/editors/space_nla/nla_header.c @@ -146,8 +146,8 @@ static void nla_editmenu(bContext *C, uiLayout *layout, void *arg_unused) uiItemO(layout, NULL, 0, "NLA_OT_add_tracks"); uiItemBooleanO(layout, "Add Tracks Above Selected", 0, "NLA_OT_add_tracks", "above_selected", 1); - uiItemO(layout, NULL, 0, "NLA_OT_add_actionclip"); - uiItemO(layout, NULL, 0, "NLA_OT_add_transition"); + uiItemO(layout, NULL, 0, "NLAEDIT_OT_add_actionclip"); + uiItemO(layout, NULL, 0, "NLAEDIT_OT_add_transition"); uiItemO(layout, NULL, 0, "NLAEDIT_OT_split"); From d525ae17829ae13640488e6f50022b317a8eba63 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 19 Jun 2009 12:45:08 +0000 Subject: [PATCH 044/114] NLA SoC: Duplicate Strips Operator (Shift D) It is now possible to Duplicate Strips again. Strips are added into the first available space in the track above the original track (or a new track above the original if there wasn't any space). Also, separated out the 'add' operators into their own menu. This might need to be changed later... --- source/blender/editors/space_nla/nla_edit.c | 88 +++++++++++++++++++ source/blender/editors/space_nla/nla_header.c | 21 +++-- source/blender/editors/space_nla/nla_intern.h | 1 + source/blender/editors/space_nla/nla_ops.c | 4 + 4 files changed, 108 insertions(+), 6 deletions(-) diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index 2996a005177..d2cf728ea58 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -440,6 +440,94 @@ void NLAEDIT_OT_add_transition (wmOperatorType *ot) ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } +/* ******************** Duplicate Strips Operator ************************** */ +/* Duplicates the selected NLA-Strips, putting them on new tracks above the one + * the originals were housed in. + */ + +static int nlaedit_duplicate_exec (bContext *C, wmOperator *op) +{ + bAnimContext ac; + + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + short done = 0; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* get a list of editable tracks being shown in the NLA */ + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* duplicate strips in tracks starting from the last one so that we're + * less likely to duplicate strips we just duplicated... + */ + for (ale= anim_data.last; ale; ale= ale->prev) { + NlaTrack *nlt= (NlaTrack *)ale->data; + AnimData *adt= BKE_animdata_from_id(ale->id); + NlaStrip *strip, *nstrip, *next; + NlaTrack *track; + + for (strip= nlt->strips.first; strip; strip= next) { + next= strip->next; + + /* if selected, split the strip at its midpoint */ + if (strip->flag & NLASTRIP_FLAG_SELECT) { + /* make a copy (assume that this is possible) */ + nstrip= copy_nlastrip(strip); + + /* in case there's no space in the track above, or we haven't got a reference to it yet, try adding */ + if (BKE_nlatrack_add_strip(nlt->next, nstrip) == 0) { + /* need to add a new track above the one above the current one + * - if the current one is the last one, nlt->next will be NULL, which defaults to adding + * at the top of the stack anyway... + */ + track= add_nlatrack(adt, nlt->next); + BKE_nlatrack_add_strip(track, nstrip); + } + + /* deselect the original */ + strip->flag &= ~NLASTRIP_FLAG_SELECT; + + done++; + } + } + } + + /* free temp data */ + BLI_freelistN(&anim_data); + + if (done) { + /* set notifier that things have changed */ + ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); + WM_event_add_notifier(C, NC_SCENE, NULL); + + /* done + allow for tweaking to be invoked */ + return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH; + } + else + return OPERATOR_CANCELLED; +} + +void NLAEDIT_OT_duplicate (wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Duplicate Strips"; + ot->idname= "NLAEDIT_OT_duplicate"; + ot->description= "Duplicate selected NLA-Strips, adding the new strips in new tracks above the originals."; + + /* api callbacks */ + ot->exec= nlaedit_duplicate_exec; + ot->poll= nlaop_poll_tweakmode_off; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + /* ******************** Delete Strips Operator ***************************** */ /* Deletes the selected NLA-Strips */ diff --git a/source/blender/editors/space_nla/nla_header.c b/source/blender/editors/space_nla/nla_header.c index 175f40befeb..f8c6ba2131a 100644 --- a/source/blender/editors/space_nla/nla_header.c +++ b/source/blender/editors/space_nla/nla_header.c @@ -143,12 +143,7 @@ static void nla_editmenu(bContext *C, uiLayout *layout, void *arg_unused) uiItemS(layout); - uiItemO(layout, NULL, 0, "NLA_OT_add_tracks"); - uiItemBooleanO(layout, "Add Tracks Above Selected", 0, "NLA_OT_add_tracks", "above_selected", 1); - - uiItemO(layout, NULL, 0, "NLAEDIT_OT_add_actionclip"); - uiItemO(layout, NULL, 0, "NLAEDIT_OT_add_transition"); - + uiItemO(layout, NULL, 0, "NLAEDIT_OT_duplicate"); uiItemO(layout, NULL, 0, "NLAEDIT_OT_split"); uiItemS(layout); @@ -156,6 +151,17 @@ static void nla_editmenu(bContext *C, uiLayout *layout, void *arg_unused) uiItemO(layout, NULL, 0, "NLAEDIT_OT_delete"); } +static void nla_addmenu(bContext *C, uiLayout *layout, void *arg_unused) +{ + uiItemO(layout, NULL, 0, "NLAEDIT_OT_add_actionclip"); + uiItemO(layout, NULL, 0, "NLAEDIT_OT_add_transition"); + + uiItemS(layout); + + uiItemO(layout, NULL, 0, "NLA_OT_add_tracks"); + uiItemBooleanO(layout, "Add Tracks Above Selected", 0, "NLA_OT_add_tracks", "above_selected", 1); +} + /* ------------------ */ static void do_nla_buttons(bContext *C, void *arg, int event) @@ -196,6 +202,9 @@ void nla_header_buttons(const bContext *C, ARegion *ar) uiDefMenuBut(block, nla_editmenu, NULL, "Edit", xco, yco, xmax-3, 20, ""); xco+= xmax; + xmax= GetButStringLength("Add"); + uiDefMenuBut(block, nla_addmenu, NULL, "Add", xco, yco, xmax-3, 20, ""); + xco+= xmax; } uiBlockSetEmboss(block, UI_EMBOSS); diff --git a/source/blender/editors/space_nla/nla_intern.h b/source/blender/editors/space_nla/nla_intern.h index f1bde40f4ab..1237542172f 100644 --- a/source/blender/editors/space_nla/nla_intern.h +++ b/source/blender/editors/space_nla/nla_intern.h @@ -95,6 +95,7 @@ void NLAEDIT_OT_tweakmode_exit(wmOperatorType *ot); void NLAEDIT_OT_add_actionclip(wmOperatorType *ot); void NLAEDIT_OT_add_transition(wmOperatorType *ot); +void NLAEDIT_OT_duplicate(wmOperatorType *ot); void NLAEDIT_OT_delete(wmOperatorType *ot); void NLAEDIT_OT_split(wmOperatorType *ot); diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c index a9b7022157e..52b529661cb 100644 --- a/source/blender/editors/space_nla/nla_ops.c +++ b/source/blender/editors/space_nla/nla_ops.c @@ -137,6 +137,7 @@ void nla_operatortypes(void) WM_operatortype_append(NLAEDIT_OT_add_actionclip); WM_operatortype_append(NLAEDIT_OT_add_transition); + WM_operatortype_append(NLAEDIT_OT_duplicate); WM_operatortype_append(NLAEDIT_OT_delete); WM_operatortype_append(NLAEDIT_OT_split); } @@ -215,6 +216,9 @@ static void nla_keymap_main (wmWindowManager *wm, ListBase *keymap) WM_keymap_add_item(keymap, "NLAEDIT_OT_add_actionclip", AKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "NLAEDIT_OT_add_transition", TKEY, KM_PRESS, KM_SHIFT, 0); + /* duplicate */ + WM_keymap_add_item(keymap, "NLAEDIT_OT_duplicate", DKEY, KM_PRESS, KM_SHIFT, 0); + /* delete */ WM_keymap_add_item(keymap, "NLAEDIT_OT_delete", XKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "NLAEDIT_OT_delete", DELKEY, KM_PRESS, 0, 0); From bb9323a720483b0c02bf25ecfca9c6ccc8699519 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 19 Jun 2009 12:57:31 +0000 Subject: [PATCH 045/114] NLA SoC: Minor Tweaks (Duplicate + Muted-Strip Drawing) * Duplicate operator now inits transform once strips have been created * Muted strips now draw with a dotted outline --- source/blender/editors/space_nla/nla_draw.c | 15 ++++++++++++++- source/blender/editors/space_nla/nla_edit.c | 20 ++++++++++++++++++-- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index 3a3f86bb5a3..9a9cbeeff21 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -68,6 +68,7 @@ #include "ED_screen.h" #include "BIF_gl.h" +#include "BIF_glutil.h" #include "WM_api.h" #include "WM_types.h" @@ -184,7 +185,10 @@ static void nla_draw_strip (AnimData *adt, NlaTrack *nlt, NlaStrip *strip, View2 uiSetRoundBox(15); /* all corners rounded */ gl_round_box_shade(GL_POLYGON, strip->start, yminc, strip->end, ymaxc, 0.0, 0.5, 0.1); - /* draw strip outline - different colors are used here... */ + + /* draw strip outline + * - color used here is to indicate active vs non-active + */ if (strip->flag & NLASTRIP_FLAG_ACTIVE) { /* strip should appear 'sunken', so draw a light border around it */ glColor3f(0.9f, 1.0f, 0.9f); // FIXME: hardcoded temp-hack colors @@ -193,7 +197,16 @@ static void nla_draw_strip (AnimData *adt, NlaTrack *nlt, NlaStrip *strip, View2 /* strip should appear to stand out, so draw a dark border around it */ glColor3f(0.0f, 0.0f, 0.0f); } + + /* - line style: dotted for muted */ + if (strip->flag & NLASTRIP_FLAG_MUTED) + setlinestyle(4); + + /* draw outline */ gl_round_box_shade(GL_LINE_LOOP, strip->start, yminc, strip->end, ymaxc, 0.0, 0.0, 0.1); + + /* reset linestyle */ + setlinestyle(0); } /* add the relevant text to the cache of text-strings to draw in pixelspace */ diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index d2cf728ea58..8b7c6bb99c6 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -59,6 +59,8 @@ #include "ED_space_api.h" #include "ED_screen.h" +#include "BIF_transform.h" + #include "RNA_access.h" #include "RNA_define.h" @@ -506,13 +508,23 @@ static int nlaedit_duplicate_exec (bContext *C, wmOperator *op) ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); WM_event_add_notifier(C, NC_SCENE, NULL); - /* done + allow for tweaking to be invoked */ - return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH; + /* done */ + return OPERATOR_FINISHED; } else return OPERATOR_CANCELLED; } +static int nlaedit_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + nlaedit_duplicate_exec(C, op); + + RNA_int_set(op->ptr, "mode", TFM_TIME_TRANSLATE); // XXX + WM_operator_name_call(C, "TFM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr); + + return OPERATOR_FINISHED; +} + void NLAEDIT_OT_duplicate (wmOperatorType *ot) { /* identifiers */ @@ -521,11 +533,15 @@ void NLAEDIT_OT_duplicate (wmOperatorType *ot) ot->description= "Duplicate selected NLA-Strips, adding the new strips in new tracks above the originals."; /* api callbacks */ + ot->invoke= nlaedit_duplicate_invoke; ot->exec= nlaedit_duplicate_exec; ot->poll= nlaop_poll_tweakmode_off; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* to give to transform */ + RNA_def_int(ot->srna, "mode", TFM_TRANSLATION, 0, INT_MAX, "Mode", "", 0, INT_MAX); } /* ******************** Delete Strips Operator ***************************** */ From 6393e9b3ca7e40e95830d009020b0f106c00b529 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sat, 20 Jun 2009 03:58:25 +0000 Subject: [PATCH 046/114] NLA SoC: Fixes for problems arising from the merge --- .../blender/editors/space_nla/nla_buttons.c | 6 +---- source/blender/editors/space_nla/nla_select.c | 8 +++---- source/blender/makesrna/intern/makesrna.c | 2 +- source/blender/makesrna/intern/rna_nla.c | 24 +++++++++---------- 4 files changed, 18 insertions(+), 22 deletions(-) diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c index cb76f7fc735..0d5cdf80830 100644 --- a/source/blender/editors/space_nla/nla_buttons.c +++ b/source/blender/editors/space_nla/nla_buttons.c @@ -206,11 +206,7 @@ static void nla_panel_properties(const bContext *C, Panel *pa) uiLayout *layout= pa->layout; uiLayout *column, *row, *subcol; uiBlock *block; - - /* check context and also validity of pointer */ - if (!nla_panel_context(C, NULL, &strip_ptr)) - return; - + block= uiLayoutGetBlock(layout); uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL); diff --git a/source/blender/editors/space_nla/nla_select.c b/source/blender/editors/space_nla/nla_select.c index b850ec76f82..ee4ed01ab81 100644 --- a/source/blender/editors/space_nla/nla_select.c +++ b/source/blender/editors/space_nla/nla_select.c @@ -361,10 +361,10 @@ void NLAEDIT_OT_select_border(wmOperatorType *ot) /* defines for left-right select tool */ static EnumPropertyItem prop_nlaedit_leftright_select_types[] = { - {NLAEDIT_LRSEL_TEST, "CHECK", "Check if Select Left or Right", ""}, - {NLAEDIT_LRSEL_NONE, "OFF", "Don't select", ""}, - {NLAEDIT_LRSEL_LEFT, "LEFT", "Before current frame", ""}, - {NLAEDIT_LRSEL_RIGHT, "RIGHT", "After current frame", ""}, + {NLAEDIT_LRSEL_TEST, "CHECK", 0, "Check if Select Left or Right", ""}, + {NLAEDIT_LRSEL_NONE, "OFF", 0, "Don't select", ""}, + {NLAEDIT_LRSEL_LEFT, "LEFT", 0, "Before current frame", ""}, + {NLAEDIT_LRSEL_RIGHT, "RIGHT", 0, "After current frame", ""}, {0, NULL, NULL, NULL} }; diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index eacf3a65c7d..18734fbcb18 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -1846,7 +1846,7 @@ RNAProcessItem PROCESS_ITEMS[]= { {"rna_mesh.c", "rna_mesh_api.c", RNA_def_mesh}, {"rna_meta.c", NULL, RNA_def_meta}, {"rna_modifier.c", NULL, RNA_def_modifier}, - {"rna_nla.c", RNA_def_nla}, + {"rna_nla.c", NULL, RNA_def_nla}, {"rna_nodetree.c", NULL, RNA_def_nodetree}, {"rna_object.c", "rna_object_api.c", RNA_def_object}, {"rna_object_force.c", NULL, RNA_def_object_force}, diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c index 4b5c14aab82..dacd257dc17 100644 --- a/source/blender/makesrna/intern/rna_nla.c +++ b/source/blender/makesrna/intern/rna_nla.c @@ -157,20 +157,20 @@ void rna_def_nlastrip(BlenderRNA *brna) /* enum defs */ static EnumPropertyItem prop_type_items[] = { - {NLASTRIP_TYPE_CLIP, "CLIP", "Action Clip", "NLA Strip references some Action."}, - {NLASTRIP_TYPE_TRANSITION, "TRANSITION", "Transition", "NLA Strip 'transitions' between adjacent strips."}, - {0, NULL, NULL, NULL}}; + {NLASTRIP_TYPE_CLIP, "CLIP", 0, "Action Clip", "NLA Strip references some Action."}, + {NLASTRIP_TYPE_TRANSITION, "TRANSITION", 0, "Transition", "NLA Strip 'transitions' between adjacent strips."}, + {0, NULL, 0, NULL, NULL}}; static EnumPropertyItem prop_mode_blend_items[] = { - {NLASTRIP_MODE_BLEND, "BLEND", "Blend", "Results of strip and accumulated results are combined in ratio governed by influence."}, - {NLASTRIP_MODE_ADD, "ADD", "Add", "Weighted result of strip is added to the accumlated results."}, - {NLASTRIP_MODE_SUBTRACT, "SUBTRACT", "Subtract", "Weighted result of strip is removed from the accumlated results."}, - {NLASTRIP_MODE_MULTIPLY, "MULITPLY", "Multiply", "Weighted result of strip is multiplied with the accumlated results."}, - {0, NULL, NULL, NULL}}; + {NLASTRIP_MODE_BLEND, "BLEND", 0, "Blend", "Results of strip and accumulated results are combined in ratio governed by influence."}, + {NLASTRIP_MODE_ADD, "ADD", 0, "Add", "Weighted result of strip is added to the accumlated results."}, + {NLASTRIP_MODE_SUBTRACT, "SUBTRACT", 0, "Subtract", "Weighted result of strip is removed from the accumlated results."}, + {NLASTRIP_MODE_MULTIPLY, "MULITPLY", 0, "Multiply", "Weighted result of strip is multiplied with the accumlated results."}, + {0, NULL, 0, NULL, NULL}}; static EnumPropertyItem prop_mode_extend_items[] = { - {NLASTRIP_EXTEND_NOTHING, "NOTHING", "Nothing", "Strip has no influence past its extents."}, - {NLASTRIP_EXTEND_HOLD, "HOLD", "Hold", "Hold the first frame if no previous strips in track, and always hold last frame."}, - {NLASTRIP_EXTEND_HOLD_FORWARD, "HOLD_FORWARD", "Hold Forward", "Only hold last frame."}, - {0, NULL, NULL, NULL}}; + {NLASTRIP_EXTEND_NOTHING, "NOTHING", 0, "Nothing", "Strip has no influence past its extents."}, + {NLASTRIP_EXTEND_HOLD, "HOLD", 0, "Hold", "Hold the first frame if no previous strips in track, and always hold last frame."}, + {NLASTRIP_EXTEND_HOLD_FORWARD, "HOLD_FORWARD", 0, "Hold Forward", "Only hold last frame."}, + {0, NULL, 0, NULL, NULL}}; /* struct definition */ srna= RNA_def_struct(brna, "NlaStrip", NULL); From 6394ee9e8143988b2a0f9316fb7bca5dc78e6e53 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sat, 20 Jun 2009 04:02:49 +0000 Subject: [PATCH 047/114] NLA SoC: Drawing + Editing Fixes * Strips using the same action as the 'tweaking action' now get the error flag cleared after tweakmode is exited. (These strips draw with red shading) * The direction in which strips get played (as a result of the 'reversed' option) now gets indicated on strips by the direction of the arrow text printed on each strip * The active strip flag is now cleared after duplicating/splitting strips. --- source/blender/blenkernel/intern/nla.c | 12 +++++++++--- source/blender/editors/space_nla/nla_draw.c | 12 +++++++++--- source/blender/editors/space_nla/nla_edit.c | 7 +++++-- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 0684d943754..1ce6d9f98c7 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -648,7 +648,6 @@ short BKE_nla_tweakmode_enter (AnimData *adt) /* if block is already in tweakmode, just leave, but we should report * that this block is in tweakmode (as our returncode) */ - // FIXME: hopefully the flag is correct! if (adt->flag & ADT_NLA_EDIT_ON) return 1; @@ -707,6 +706,7 @@ short BKE_nla_tweakmode_enter (AnimData *adt) /* Exit tweakmode for this AnimData block */ void BKE_nla_tweakmode_exit (AnimData *adt) { + NlaStrip *strip; NlaTrack *nlt; /* verify that data is valid */ @@ -719,9 +719,15 @@ void BKE_nla_tweakmode_exit (AnimData *adt) // TODO: need to sync the user-strip with the new state of the action! - /* for all NLA-tracks, clear the 'disabled' flag */ - for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) + /* for all NLA-tracks, clear the 'disabled' flag + * for all NLA-strips, clear the 'tweak-user' flag + */ + for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) { nlt->flag &= ~NLATRACK_DISABLED; + + for (strip= nlt->strips.first; strip; strip= strip->next) + strip->flag &= ~NLASTRIP_FLAG_TWEAKUSER; + } /* handle AnimData level changes: * - 'temporary' active action needs its usercount decreased, since we're removing this reference diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index 9a9cbeeff21..2ac2b557243 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -212,19 +212,25 @@ static void nla_draw_strip (AnimData *adt, NlaTrack *nlt, NlaStrip *strip, View2 /* add the relevant text to the cache of text-strings to draw in pixelspace */ static void nla_draw_strip_text (NlaTrack *nlt, NlaStrip *strip, int index, View2D *v2d, float yminc, float ymaxc) { - char str[256]; + char str[256], dir[3]; rctf rect; + /* 'dir' - direction that strip is played in */ + if (strip->flag & NLASTRIP_FLAG_REVERSE) + sprintf(dir, "<-"); + else + sprintf(dir, "->"); + /* for now, just init the string with fixed-formats */ switch (strip->type) { case NLASTRIP_TYPE_TRANSITION: /* Transition */ - sprintf(str, "%d | Transition | %.2f <-> %.2f", index, strip->start, strip->end); + sprintf(str, "%d | Transition | %.2f %s %.2f", index, strip->start, dir, strip->end); break; case NLASTRIP_TYPE_CLIP: /* Action-Clip (default) */ default: if (strip->act) - sprintf(str, "%d | Act: %s | %.2f <-> %.2f", index, strip->act->id.name+2, strip->start, strip->end); + sprintf(str, "%d | Act: %s | %.2f %s %.2f", index, strip->act->id.name+2, strip->start, dir, strip->end); else sprintf(str, "%d | Act: ", index); // xxx... need a better format? break; diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index 8b7c6bb99c6..ebb0589a82d 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -492,8 +492,8 @@ static int nlaedit_duplicate_exec (bContext *C, wmOperator *op) BKE_nlatrack_add_strip(track, nstrip); } - /* deselect the original */ - strip->flag &= ~NLASTRIP_FLAG_SELECT; + /* deselect the original and the active flag */ + strip->flag &= ~(NLASTRIP_FLAG_SELECT|NLASTRIP_FLAG_ACTIVE); done++; } @@ -666,6 +666,9 @@ static int nlaedit_split_exec (bContext *C, wmOperator *op) strip->actend= midaframe; nstrip->actstart= midaframe; + + /* clear the active flag from the copy */ + nstrip->flag &= ~NLASTRIP_FLAG_ACTIVE; } } } From ef7860ed9a68e3b92346697028ef0bdd9d21932f Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sat, 20 Jun 2009 09:36:55 +0000 Subject: [PATCH 048/114] NLA SoC: Conversions for old NLA-data to the new system Old NLA-data now gets mostly ported converted over to the new system, with strips and their respective Actions being handled correctly in the test cases I've got. The conversion procedure now tries to fit multiple strips into since tracks as it is assumed that quite a few old setups tried to do. However, some old setups may be adversely affected by this (i.e. if they depend on a certain order of holding adds for example). For now, there are no complete replacements for the NLA-Modifier/Auto-Walking stuff yet, so that info is currently just ignored (but correctly freed). The current plan here is to get Armature-level pose-offset system + F-Modifiers where appropriate. This should be one of the major causes of file breakage now... Also, I've yet to restore some patching for group instancing NLA stuff, since more trickery here is required. This is probably the second major cause of file breakage... --- source/blender/blenkernel/intern/ipo.c | 111 ++++++++++++++++++++++++- 1 file changed, 107 insertions(+), 4 deletions(-) diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index 54618813a0b..5642e63326f 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -58,6 +58,7 @@ #include "DNA_key_types.h" #include "DNA_material_types.h" #include "DNA_mesh_types.h" +#include "DNA_nla_types.h" #include "DNA_object_types.h" #include "DNA_object_force.h" #include "DNA_particle_types.h" @@ -85,6 +86,7 @@ #include "BKE_library.h" #include "BKE_main.h" #include "BKE_mesh.h" +#include "BKE_nla.h" #include "BKE_object.h" @@ -1463,6 +1465,87 @@ static void action_to_animdata (ID *id, bAction *act) action_to_animato(act, &adt->action->groups, &adt->action->curves, &adt->drivers); } +/* ------------------------- */ + +// TODO: +// - NLA group duplicators info +// - NLA curve/stride modifiers... + +/* Convert NLA-Strip to new system */ +static void nlastrips_to_animdata (ID *id, ListBase *strips) +{ + AnimData *adt= BKE_animdata_from_id(id); + NlaTrack *nlt = NULL; + NlaStrip *strip; + bActionStrip *as, *asn; + + /* for each one of the original strips, convert to a new strip and free the old... */ + for (as= strips->first; as; as= asn) { + asn= as->next; + + /* this old strip is only worth something if it had an action... */ + if (as->act) { + /* convert Action data (if not yet converted), storing the results in the same Action */ + action_to_animato(as->act, &as->act->groups, &as->act->curves, &adt->drivers); + + /* create a new-style NLA-strip which references this Action, then copy over relevant settings */ + { + /* init a new strip, and assign the action to it + * - no need to muck around with the user-counts, since this is just + * passing over the ref to the new owner, not creating an additional ref + */ + strip= MEM_callocN(sizeof(NlaStrip), "NlaStrip"); + strip->act= as->act; + + /* endpoints */ + strip->start= as->start; + strip->end= as->end; + strip->actstart= as->actstart; + strip->actend= as->actend; + + /* action reuse */ + strip->repeat= as->repeat; + strip->scale= as->scale; + if (as->flag & ACTSTRIP_LOCK_ACTION) strip->flag |= NLASTRIP_FLAG_SYNC_LENGTH; + + /* blending */ + strip->blendin= as->blendin; + strip->blendout= as->blendout; + strip->blendmode= (as->mode==ACTSTRIPMODE_ADD) ? NLASTRIP_MODE_ADD : NLASTRIP_MODE_BLEND; + if (as->flag & ACTSTRIP_AUTO_BLENDS) strip->flag |= NLASTRIP_FLAG_AUTO_BLENDS; + + /* assorted setting flags */ + if (as->flag & ACTSTRIP_SELECT) strip->flag |= NLASTRIP_FLAG_SELECT; + if (as->flag & ACTSTRIP_ACTIVE) strip->flag |= NLASTRIP_FLAG_ACTIVE; + + if (as->flag & ACTSTRIP_MUTE) strip->flag |= NLASTRIP_FLAG_MUTED; + if (as->flag & ACTSTRIP_REVERSE) strip->flag |= NLASTRIP_FLAG_REVERSE; + + /* by default, we now always extrapolate, while in the past this was optional */ + if ((as->flag & ACTSTRIP_HOLDLASTFRAME)==0) + strip->extendmode= NLASTRIP_EXTEND_NOTHING; + } + + /* try to add this strip to the current NLA-Track (i.e. the 'last' one on the stack atm) */ + if (BKE_nlatrack_add_strip(nlt, strip) == 0) { + /* trying to add to the current failed (no space), + * so add a new track to the stack, and add to that... + */ + nlt= add_nlatrack(adt, NULL); + BKE_nlatrack_add_strip(nlt, strip); + } + } + + /* modifiers */ + // FIXME: for now, we just free them... + if (as->modifiers.first) + BLI_freelistN(&as->modifiers); + + /* free the old strip */ + BLI_freelinkN(strips, as); + } +} + /* *************************************************** */ /* External API - Only Called from do_versions() */ @@ -1509,7 +1592,30 @@ void do_versions_ipos_to_animato(Main *main) if (G.f & G_DEBUG) printf("\tconverting ob %s \n", id->name+2); /* check if object has any animation data */ - if ((ob->ipo) || (ob->action) || (ob->nlastrips.first)) { + if (ob->nlastrips.first) { + /* Add AnimData block */ + adt= BKE_id_add_animdata(id); + + /* IPO first to take into any non-NLA'd Object Animation */ + if (ob->ipo) { + ipo_to_animdata(id, ob->ipo, NULL, NULL); + + ob->ipo->id.us--; + ob->ipo= NULL; + } + + /* Action is skipped since it'll be used by some strip in the NLA anyway, + * causing errors with evaluation in the new evaluation pipeline + */ + if (ob->action) { + ob->action->id.us--; + ob->action= NULL; + } + + /* finally NLA */ + nlastrips_to_animdata(id, &ob->nlastrips); + } + else if ((ob->ipo) || (ob->action)) { /* Add AnimData block */ adt= BKE_id_add_animdata(id); @@ -1530,9 +1636,6 @@ void do_versions_ipos_to_animato(Main *main) ob->ipo->id.us--; ob->ipo= NULL; } - - /* finally NLA */ - // XXX todo... for now, new NLA code not hooked up yet, so keep old stuff (but not for too long!) } /* check PoseChannels for constraints with local data */ From 6ff4a7229f316548046ab5593070b082cc1a4a7a Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sat, 20 Jun 2009 11:44:56 +0000 Subject: [PATCH 049/114] NLA SoC: Conversion fixes - Curve 'Speed' Curves + Constraints These fixes get the 'pathJumper.blend' file from our testing suite workable in 2.5 (with a few minor tweaks still needed *) Changes required: - Added a 'ctime' var to curve structs for storing the value that used to be obtained by specially evaluating the 'speed' curve when evaluating objects parented to the curve. This can now be animated as a 'proper' var as per normal. - Added a special hack for detecting constraint blocks, as the old method resulted in paths for Objects instead... (*) Issues: - Unfortunately, the paths still don't work out of the box. For some reason, the constraint names in the paths are spelt incorrectly - "Ar" and "Br" instead of "Ap" and "Bp". I'm not sure where this problem is coming from, but changing the paths manually in the Datablocks viewer fixes this error... - I noticed that in the buttons view, only 1st of the constraints gets shown. This seems a bit like some of the intermittent problems I've had with some arrays/lists not expanding properly in Datablocks view. --- source/blender/blenkernel/intern/anim_sys.c | 14 +++++++++++++- source/blender/blenkernel/intern/ipo.c | 11 +++++++++-- source/blender/blenkernel/intern/object.c | 16 ++++++++-------- source/blender/makesdna/DNA_curve_types.h | 5 +++-- source/blender/makesrna/intern/rna_curve.c | 6 ++++++ 5 files changed, 39 insertions(+), 13 deletions(-) diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 2efb4f2b2d3..7a6706b7c5a 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -1341,10 +1341,22 @@ void BKE_animsys_evaluate_all_animation (Main *main, float ctime) EVAL_ANIM_IDS(main->camera.first, ADT_RECALC_ANIM); /* shapekeys */ + // TODO: we probably need the same hack as for curves (ctime-hack) EVAL_ANIM_IDS(main->key.first, ADT_RECALC_ANIM); /* curves */ - // TODO... + /* we need to perform a special hack here to ensure that the ctime + * value of the curve gets set in case there's no animation for that + * - it needs to be set before animation is evaluated just so that + * animation can successfully override... + */ + for (id= main->curve.first; id; id= id->next) { + AnimData *adt= BKE_animdata_from_id(id); + Curve *cu= (Curve *)id; + + cu->ctime= ctime; + BKE_animsys_evaluate_animdata(id, adt, ctime, ADT_RECALC_ANIM); + } /* meshes */ // TODO... diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index 5642e63326f..968a0e68fb9 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -827,6 +827,10 @@ char *get_rna_access (int blocktype, int adrcode, char actname[], char constname char buf[512]; int dummy_index= 0; + /* hack: if constname is set, we can only be dealing with an Constraint curve */ + if (constname) + blocktype= ID_CO; + /* get property name based on blocktype */ switch (blocktype) { case ID_OB: /* object */ @@ -842,7 +846,7 @@ char *get_rna_access (int blocktype, int adrcode, char actname[], char constname break; case ID_CO: /* constraint */ - propname= constraint_adrcodes_to_paths(adrcode, &dummy_index); + propname= constraint_adrcodes_to_paths(adrcode, &dummy_index); break; case ID_TE: /* texture */ @@ -872,7 +876,10 @@ char *get_rna_access (int blocktype, int adrcode, char actname[], char constname /* XXX problematic blocktypes */ case ID_CU: /* curve */ - propname= "speed"; // XXX this was a 'dummy curve' that didn't really correspond to any real var... + /* this used to be a 'dummy' curve which got evaluated on the fly... + * now we've got real var for this! + */ + propname= "eval_time"; break; case ID_SEQ: /* sequencer strip */ diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index c2916bc2231..6490ff3c724 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -1569,14 +1569,14 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[][4]) } /* catch exceptions: curve paths used as a duplicator */ else if(enable_cu_speed) { - ctime= bsystem_time(scene, ob, (float)scene->r.cfra, 0.0); - -#if 0 // XXX old animation system - if(calc_ipo_spec(cu->ipo, CU_SPEED, &ctime)==0) { - ctime /= cu->pathlen; - CLAMP(ctime, 0.0, 1.0); - } -#endif // XXX old animation system + /* 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... + * + * we firstly calculate the modulus of cu->ctime/cu->pathlen to clamp ctime within the 0.0 to 1.0 times pathlen + * range, then divide this (the modulus) by pathlen to get a value between 0.0 and 1.0 + */ + ctime= fmod(cu->ctime, cu->pathlen) / cu->pathlen; + CLAMP(ctime, 0.0, 1.0); } else { ctime= scene->r.cfra - give_timeoffset(ob); diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h index f8ea5f95d65..b0f089d670f 100644 --- a/source/blender/makesdna/DNA_curve_types.h +++ b/source/blender/makesdna/DNA_curve_types.h @@ -148,7 +148,7 @@ typedef struct Curve { ListBase *editnurb; /* edited data, not in file, use pointer so we can check for it */ struct Object *bevobj, *taperobj, *textoncurve; - struct Ipo *ipo; + struct Ipo *ipo; // XXX depreceated... old animation system Path *path; struct Key *key; struct Material **mat; @@ -193,7 +193,8 @@ typedef struct Curve { int sepchar; - int totbox, actbox, pad; + float ctime; /* current evaltime - for use by Objects parented to curves */ + int totbox, actbox; struct TextBox *tb; int selstart, selend; diff --git a/source/blender/makesrna/intern/rna_curve.c b/source/blender/makesrna/intern/rna_curve.c index 41a47e279e9..91488aa2a49 100644 --- a/source/blender/makesrna/intern/rna_curve.c +++ b/source/blender/makesrna/intern/rna_curve.c @@ -31,6 +31,7 @@ #include "DNA_curve_types.h" #include "DNA_material_types.h" +#include "DNA_scene_types.h" EnumPropertyItem beztriple_handle_type_items[] = { {HD_FREE, "FREE", 0, "Free", ""}, @@ -558,6 +559,11 @@ static void rna_def_curve(BlenderRNA *brna) RNA_def_property_ui_range(prop, 1, 1024, 1, 0); RNA_def_property_ui_text(prop, "Render Resolution V", "Surface resolution in V direction used while rendering. Zero skips this property."); + + prop= RNA_def_property(srna, "eval_time", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "ctime"); + RNA_def_property_ui_text(prop, "Evaluation Time", "Parametric position along the length of the curve that Objects 'following' it should be at."); + /* pointers */ prop= RNA_def_property(srna, "bevel_object", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "bevobj"); From 6bca54aac17212f9c40b0a54a50a6c39e0817815 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sun, 21 Jun 2009 02:03:50 +0000 Subject: [PATCH 050/114] NLA SoC: Click-Select Operator and TweakMode To make TweakMode seem less modal/blocking, selection now works in TweakMode. The caveat though, is that TweakMode must be immediately exited as a result of this, or else the internal state could become rather inconsistent and confused. All other operators will still continue to operate as per normal though, since in TweakMode, some operations are still very dangerous. --- source/blender/editors/space_nla/nla_select.c | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/source/blender/editors/space_nla/nla_select.c b/source/blender/editors/space_nla/nla_select.c index ee4ed01ab81..28027d0d9cd 100644 --- a/source/blender/editors/space_nla/nla_select.c +++ b/source/blender/editors/space_nla/nla_select.c @@ -365,7 +365,7 @@ static EnumPropertyItem prop_nlaedit_leftright_select_types[] = { {NLAEDIT_LRSEL_NONE, "OFF", 0, "Don't select", ""}, {NLAEDIT_LRSEL_LEFT, "LEFT", 0, "Before current frame", ""}, {NLAEDIT_LRSEL_RIGHT, "RIGHT", 0, "After current frame", ""}, - {0, NULL, NULL, NULL} + {0, NULL, 0, NULL, NULL} }; /* sensitivity factor for frame-selections */ @@ -375,13 +375,14 @@ static EnumPropertyItem prop_nlaedit_leftright_select_types[] = { /* ------------------- */ /* option 1) select strip directly under mouse */ -static void mouse_nla_strips (bAnimContext *ac, int mval[2], short select_mode) +static void mouse_nla_strips (bContext *C, bAnimContext *ac, int mval[2], short select_mode) { ListBase anim_data = {NULL, NULL}; bAnimListElem *ale = NULL; int filter; View2D *v2d= &ac->ar->v2d; + Scene *scene= ac->scene; NlaStrip *strip = NULL; int channel_index; float xmin, xmax, dummy; @@ -429,6 +430,12 @@ static void mouse_nla_strips (bAnimContext *ac, int mval[2], short select_mode) BLI_freelistN(&anim_data); } + /* if currently in tweakmode, exit tweakmode before changing selection states + * now that we've found our target... + */ + if (scene->flag & SCE_NLA_EDIT_ON) + WM_operator_name_call(C, "NLAEDIT_OT_tweakmode_exit", WM_OP_EXEC_DEFAULT, NULL); + /* for replacing selection, firstly need to clear existing selection */ if (select_mode == SELECT_REPLACE) { /* reset selection mode for next steps */ @@ -470,7 +477,7 @@ static void mouse_nla_strips (bAnimContext *ac, int mval[2], short select_mode) } /* Option 2) Selects all the strips on either side of the current frame (depends on which side the mouse is on) */ -static void nlaedit_mselect_leftright (bAnimContext *ac, short leftright, short select_mode) +static void nlaedit_mselect_leftright (bContext *C, bAnimContext *ac, short leftright, short select_mode) { ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; @@ -479,6 +486,10 @@ static void nlaedit_mselect_leftright (bAnimContext *ac, short leftright, short Scene *scene= ac->scene; float xmin, xmax; + /* if currently in tweakmode, exit tweakmode first */ + if (scene->flag & SCE_NLA_EDIT_ON) + WM_operator_name_call(C, "NLAEDIT_OT_tweakmode_exit", WM_OP_EXEC_DEFAULT, NULL); + /* if select mode is replace, deselect all keyframes (and channels) first */ if (select_mode==SELECT_REPLACE) { select_mode= SELECT_ADD; @@ -564,11 +575,11 @@ static int nlaedit_clickselect_invoke(bContext *C, wmOperator *op, wmEvent *even else RNA_int_set(op->ptr, "left_right", NLAEDIT_LRSEL_RIGHT); - nlaedit_mselect_leftright(&ac, RNA_enum_get(op->ptr, "left_right"), selectmode); + nlaedit_mselect_leftright(C, &ac, RNA_enum_get(op->ptr, "left_right"), selectmode); } else { /* select strips based upon mouse position */ - mouse_nla_strips(&ac, mval, selectmode); + mouse_nla_strips(C, &ac, mval, selectmode); } /* set notifier that things have changed */ @@ -586,7 +597,7 @@ void NLAEDIT_OT_click_select (wmOperatorType *ot) /* api callbacks - absolutely no exec() this yet... */ ot->invoke= nlaedit_clickselect_invoke; - ot->poll= nlaop_poll_tweakmode_off; + ot->poll= ED_operator_nla_active; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; From ed316ad8e967b85a79bb67b79ffc5e3cd90820a5 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sun, 21 Jun 2009 03:02:40 +0000 Subject: [PATCH 051/114] NLA SoC: Fixes for Operator Poll Callbacks * Clicking on NLA tracks while in TweakMode now works so that channels can be muted/protected/expanded as per usual. However, they cannot be selected, as changing the selection state can interfere with TweakMode state changes * Operators for animation channel-lists now use proper poll callbacks, which also take into account TweakMode where appropriate (i.e. all selection operators are now allowed to operate in NLA while in TweakMode, and all other operators will only work in Animation Editors) * Action Editor operators now use the poll callback for Action Editors/DopeSheet instead of the generic active-araa one. --- .../blender/editors/animation/anim_channels.c | 59 ++++++++++++++++--- .../editors/space_action/action_edit.c | 30 +++++----- .../editors/space_action/action_select.c | 8 +-- .../blender/editors/space_nla/nla_channels.c | 16 ++--- source/blender/editors/space_nla/nla_edit.c | 2 +- source/blender/editors/space_nla/nla_intern.h | 2 + source/blender/editors/space_nla/nla_ops.c | 12 +++- 7 files changed, 91 insertions(+), 38 deletions(-) diff --git a/source/blender/editors/animation/anim_channels.c b/source/blender/editors/animation/anim_channels.c index d753f65ff50..9230cdfc9a2 100644 --- a/source/blender/editors/animation/anim_channels.c +++ b/source/blender/editors/animation/anim_channels.c @@ -271,6 +271,47 @@ void ANIM_deselect_anim_channels (void *data, short datatype, short test, short /* ************************************************************************** */ /* OPERATORS */ +/* ****************** Operator Utilities ********************************** */ + +/* poll callback for being in an Animation Editor channels list region */ +int animedit_poll_channels_active (bContext *C) +{ + ScrArea *sa= CTX_wm_area(C); + + /* channels region test */ + // TODO: could enhance with actually testing if channels region? + if (ELEM(NULL, sa, CTX_wm_region(C))) + return 0; + /* animation editor test */ + if (ELEM3(sa->spacetype, SPACE_ACTION, SPACE_IPO, SPACE_NLA) == 0) + return 0; + + return 1; +} + +/* poll callback for Animation Editor channels list region + not in NLA-tweakmode for NLA */ +int animedit_poll_channels_nla_tweakmode_off (bContext *C) +{ + ScrArea *sa= CTX_wm_area(C); + Scene *scene = CTX_data_scene(C); + + /* channels region test */ + // TODO: could enhance with actually testing if channels region? + if (ELEM(NULL, sa, CTX_wm_region(C))) + return 0; + /* animation editor test */ + if (ELEM3(sa->spacetype, SPACE_ACTION, SPACE_IPO, SPACE_NLA) == 0) + return 0; + + /* NLA TweakMode test */ + if (sa->spacetype == SPACE_NLA) { + if ((scene == NULL) || (scene->flag & SCE_NLA_EDIT_ON)) + return 0; + } + + return 1; +} + /* ****************** Rearrange Channels Operator ******************* */ /* This operator only works for Action Editor mode for now, as having it elsewhere makes things difficult */ @@ -961,7 +1002,7 @@ void ANIM_OT_channels_setting_enable (wmOperatorType *ot) /* api callbacks */ ot->invoke= WM_menu_invoke; ot->exec= animchannels_setflag_exec; - ot->poll= ED_operator_areaactive; + ot->poll= animedit_poll_channels_active; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -982,7 +1023,7 @@ void ANIM_OT_channels_setting_disable (wmOperatorType *ot) /* api callbacks */ ot->invoke= WM_menu_invoke; ot->exec= animchannels_setflag_exec; - ot->poll= ED_operator_areaactive; + ot->poll= animedit_poll_channels_active; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -1003,7 +1044,7 @@ void ANIM_OT_channels_setting_toggle (wmOperatorType *ot) /* api callbacks */ ot->invoke= WM_menu_invoke; ot->exec= animchannels_setflag_exec; - ot->poll= ED_operator_areaactive; + ot->poll= animedit_poll_channels_active; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -1024,7 +1065,7 @@ void ANIM_OT_channels_editable_toggle (wmOperatorType *ot) /* api callbacks */ ot->exec= animchannels_setflag_exec; - ot->poll= ED_operator_areaactive; + ot->poll= animedit_poll_channels_active; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -1068,7 +1109,7 @@ void ANIM_OT_channels_expand (wmOperatorType *ot) /* api callbacks */ ot->exec= animchannels_expand_exec; - ot->poll= ED_operator_areaactive; + ot->poll= animedit_poll_channels_active; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -1109,7 +1150,7 @@ void ANIM_OT_channels_collapse (wmOperatorType *ot) /* api callbacks */ ot->exec= animchannels_collapse_exec; - ot->poll= ED_operator_areaactive; + ot->poll= animedit_poll_channels_active; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -1148,7 +1189,7 @@ void ANIM_OT_channels_select_all_toggle (wmOperatorType *ot) /* api callbacks */ ot->exec= animchannels_deselectall_exec; - ot->poll= ED_operator_areaactive; + ot->poll= animedit_poll_channels_nla_tweakmode_off; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -1277,7 +1318,7 @@ void ANIM_OT_channels_select_border(wmOperatorType *ot) ot->exec= animchannels_borderselect_exec; ot->modal= WM_border_select_modal; - ot->poll= ED_operator_areaactive; + ot->poll= animedit_poll_channels_nla_tweakmode_off; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -1636,7 +1677,7 @@ void ANIM_OT_channels_click (wmOperatorType *ot) /* api callbacks */ ot->invoke= animchannels_mouseclick_invoke; - ot->poll= ED_operator_areaactive; + ot->poll= animedit_poll_channels_active; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index a0f1adbd97e..27be82ccec0 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -181,7 +181,7 @@ void ACT_OT_previewrange_set (wmOperatorType *ot) /* api callbacks */ ot->exec= actkeys_previewrange_exec; - ot->poll= ED_operator_areaactive; + ot->poll= ED_operator_action_active; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -228,7 +228,7 @@ void ACT_OT_view_all (wmOperatorType *ot) /* api callbacks */ ot->exec= actkeys_viewall_exec; - ot->poll= ED_operator_areaactive; + ot->poll= ED_operator_action_active; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -315,7 +315,7 @@ void ACT_OT_keyframes_copy (wmOperatorType *ot) /* api callbacks */ ot->exec= actkeys_copy_exec; - ot->poll= ED_operator_areaactive; + ot->poll= ED_operator_action_active; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -359,7 +359,7 @@ void ACT_OT_keyframes_paste (wmOperatorType *ot) /* api callbacks */ ot->exec= actkeys_paste_exec; - ot->poll= ED_operator_areaactive; + ot->poll= ED_operator_action_active; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -456,7 +456,7 @@ void ACT_OT_keyframes_insert (wmOperatorType *ot) /* api callbacks */ ot->invoke= WM_menu_invoke; ot->exec= actkeys_insertkey_exec; - ot->poll= ED_operator_areaactive; + ot->poll= ED_operator_action_active; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -533,7 +533,7 @@ void ACT_OT_keyframes_duplicate (wmOperatorType *ot) /* api callbacks */ ot->invoke= actkeys_duplicate_invoke; ot->exec= actkeys_duplicate_exec; - ot->poll= ED_operator_areaactive; + ot->poll= ED_operator_action_active; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -600,7 +600,7 @@ void ACT_OT_keyframes_delete (wmOperatorType *ot) /* api callbacks */ ot->invoke= WM_operator_confirm; ot->exec= actkeys_delete_exec; - ot->poll= ED_operator_areaactive; + ot->poll= ED_operator_action_active; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -663,7 +663,7 @@ void ACT_OT_keyframes_clean (wmOperatorType *ot) /* api callbacks */ //ot->invoke= // XXX we need that number popup for this! ot->exec= actkeys_clean_exec; - ot->poll= ED_operator_areaactive; + ot->poll= ED_operator_action_active; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -786,7 +786,7 @@ void ACT_OT_keyframes_sample (wmOperatorType *ot) /* api callbacks */ ot->exec= actkeys_sample_exec; - ot->poll= ED_operator_areaactive; + ot->poll= ED_operator_action_active; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -862,7 +862,7 @@ void ACT_OT_keyframes_extrapolation_type_set (wmOperatorType *ot) /* api callbacks */ ot->invoke= WM_menu_invoke; ot->exec= actkeys_expo_exec; - ot->poll= ED_operator_areaactive; + ot->poll= ED_operator_action_active; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -932,7 +932,7 @@ void ACT_OT_keyframes_interpolation_type (wmOperatorType *ot) /* api callbacks */ ot->invoke= WM_menu_invoke; ot->exec= actkeys_ipo_exec; - ot->poll= ED_operator_areaactive; + ot->poll= ED_operator_action_active; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -1020,7 +1020,7 @@ void ACT_OT_keyframes_handle_type_set (wmOperatorType *ot) /* api callbacks */ ot->invoke= WM_menu_invoke; ot->exec= actkeys_handletype_exec; - ot->poll= ED_operator_areaactive; + ot->poll= ED_operator_action_active; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -1079,7 +1079,7 @@ void ACT_OT_keyframes_cfrasnap (wmOperatorType *ot) /* api callbacks */ ot->exec= actkeys_cfrasnap_exec; - ot->poll= ED_operator_areaactive; + ot->poll= ED_operator_action_active; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -1175,7 +1175,7 @@ void ACT_OT_keyframes_snap (wmOperatorType *ot) /* api callbacks */ ot->invoke= WM_menu_invoke; ot->exec= actkeys_snap_exec; - ot->poll= ED_operator_areaactive; + ot->poll= ED_operator_action_active; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -1291,7 +1291,7 @@ void ACT_OT_keyframes_mirror (wmOperatorType *ot) /* api callbacks */ ot->invoke= WM_menu_invoke; ot->exec= actkeys_mirror_exec; - ot->poll= ED_operator_areaactive; + ot->poll= ED_operator_action_active; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c index 6bfdf77e2e7..f99a08bc26d 100644 --- a/source/blender/editors/space_action/action_select.c +++ b/source/blender/editors/space_action/action_select.c @@ -187,7 +187,7 @@ void ACT_OT_keyframes_select_all_toggle (wmOperatorType *ot) /* api callbacks */ ot->exec= actkeys_deselectall_exec; - ot->poll= ED_operator_areaactive; + ot->poll= ED_operator_action_active; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -349,7 +349,7 @@ void ACT_OT_keyframes_select_border(wmOperatorType *ot) ot->exec= actkeys_borderselect_exec; ot->modal= WM_border_select_modal; - ot->poll= ED_operator_areaactive; + ot->poll= ED_operator_action_active; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -563,7 +563,7 @@ void ACT_OT_keyframes_select_column (wmOperatorType *ot) /* api callbacks */ ot->exec= actkeys_columnselect_exec; - ot->poll= ED_operator_areaactive; + ot->poll= ED_operator_action_active; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -968,7 +968,7 @@ void ACT_OT_keyframes_clickselect (wmOperatorType *ot) /* api callbacks - absolutely no exec() this yet... */ ot->invoke= actkeys_clickselect_invoke; - ot->poll= ED_operator_areaactive; + ot->poll= ED_operator_action_active; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c index f928daa523b..a1c0de1e552 100644 --- a/source/blender/editors/space_nla/nla_channels.c +++ b/source/blender/editors/space_nla/nla_channels.c @@ -143,7 +143,7 @@ static void mouse_nla_channels (bAnimContext *ac, float x, int channel_index, sh /* toggle expand */ ob->nlaflag ^= OB_ADS_COLLAPSED; // XXX } - else { + else if (nlaedit_is_tweakmode_on(ac) == 0) { /* set selection status */ if (selectmode == SELECT_INVERT) { /* swap select */ @@ -242,7 +242,7 @@ static void mouse_nla_channels (bAnimContext *ac, float x, int channel_index, sh /* toggle 'solo' */ BKE_nlatrack_solo_toggle(adt, nlt); } - else { + else if (nlaedit_is_tweakmode_on(ac) == 0) { /* set selection */ if (selectmode == SELECT_INVERT) { /* inverse selection status of this F-Curve only */ @@ -266,10 +266,12 @@ static void mouse_nla_channels (bAnimContext *ac, float x, int channel_index, sh /* for now, only do something if user clicks on the 'push-down' button */ if (x >= (NLACHANNEL_NAMEWIDTH-NLACHANNEL_BUTTON_WIDTH)) { - /* activate push-down function */ - // TODO: make this use the operator instead of calling the function directly - // however, calling the operator requires that we supply the args, and that works with proper buttons only - BKE_nla_action_pushdown(adt); + /* activate push-down function - only usable when not in TweakMode */ + if (nlaedit_is_tweakmode_on(ac) == 0) { + // TODO: make this use the operator instead of calling the function directly + // however, calling the operator requires that we supply the args, and that works with proper buttons only + BKE_nla_action_pushdown(adt); + } } } break; @@ -339,7 +341,7 @@ void NLA_OT_channels_click (wmOperatorType *ot) /* api callbacks */ ot->invoke= nlachannels_mouseclick_invoke; - ot->poll= nlaop_poll_tweakmode_off; // xxx? + ot->poll= ED_operator_nla_active; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index ebb0589a82d..70a033052bd 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -625,7 +625,7 @@ static int nlaedit_split_exec (bContext *C, wmOperator *op) filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT); ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - /* for each NLA-Track, delete all selected strips */ + /* for each NLA-Track, split all selected strips into two strips */ for (ale= anim_data.first; ale; ale= ale->next) { NlaTrack *nlt= (NlaTrack *)ale->data; NlaStrip *strip, *nstrip, *next; diff --git a/source/blender/editors/space_nla/nla_intern.h b/source/blender/editors/space_nla/nla_intern.h index 1237542172f..79ee5396f36 100644 --- a/source/blender/editors/space_nla/nla_intern.h +++ b/source/blender/editors/space_nla/nla_intern.h @@ -113,6 +113,8 @@ void NLA_OT_add_tracks(wmOperatorType *ot); int nlaop_poll_tweakmode_off(bContext *C); int nlaop_poll_tweakmode_on (bContext *C); +short nlaedit_is_tweakmode_on(bAnimContext *ac); + /* --- */ void nla_operatortypes(void); diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c index 52b529661cb..df731e9d0fb 100644 --- a/source/blender/editors/space_nla/nla_ops.c +++ b/source/blender/editors/space_nla/nla_ops.c @@ -113,6 +113,14 @@ int nlaop_poll_tweakmode_on (bContext *C) return 1; } +/* is tweakmode enabled - for use in NLA operator code */ +short nlaedit_is_tweakmode_on (bAnimContext *ac) +{ + if (ac && ac->scene) + return (ac->scene->flag & SCE_NLA_EDIT_ON); + return 0; +} + /* ************************** registration - operator types **********************************/ void nla_operatortypes(void) @@ -160,10 +168,10 @@ static void nla_keymap_channels (wmWindowManager *wm, ListBase *keymap) /* General Animation Channels keymap (see anim_channels.c) ----------------------- */ /* selection */ - /* borderselect */ + /* borderselect - not in tweakmode */ WM_keymap_add_item(keymap, "ANIM_OT_channels_select_border", BKEY, KM_PRESS, 0, 0); - /* deselect all */ + /* deselect all - not in tweakmode */ WM_keymap_add_item(keymap, "ANIM_OT_channels_select_all_toggle", AKEY, KM_PRESS, 0, 0); RNA_boolean_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_select_all_toggle", IKEY, KM_PRESS, KM_CTRL, 0)->ptr, "invert", 1); From aea9dd598c72fa5ee4bcbe6198b3b81e739373a1 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Mon, 22 Jun 2009 03:26:36 +0000 Subject: [PATCH 052/114] NLA SoC: DopeSheet Cleanups * Replaced old-style menu defines with the new-style Layout Engine ones. These are now much cleaner as a result :) * Wrapped DopeSheet and Graph Editors in RNA to allow them to use the new Layout Engine for menu drawing * Shortened the names of operators in the DopeSheet, removing the "keyframes" prefix since that's the only real context which can operate there. * Standardised a few names, and renamed a confusingly named operator (cfrasnap -> jump to frame) --- source/blender/editors/include/ED_anim_api.h | 3 +- .../editors/space_action/action_edit.c | 60 +- .../editors/space_action/action_header.c | 1643 ++--------------- .../editors/space_action/action_intern.h | 35 +- .../blender/editors/space_action/action_ops.c | 89 +- .../editors/space_action/action_select.c | 16 +- source/blender/editors/space_nla/nla_header.c | 5 + source/blender/makesrna/RNA_access.h | 2 + source/blender/makesrna/intern/rna_space.c | 102 +- 9 files changed, 370 insertions(+), 1585 deletions(-) diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index e44c7ff5603..8c54c4e8f67 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -142,7 +142,6 @@ typedef enum eAnim_KeyType { ALE_GPFRAME, /* Grease Pencil Frames */ ALE_NLASTRIP, /* NLA Strips */ - // XXX the following are for summaries... should these be kept? ALE_SCE, /* Scene summary */ ALE_OB, /* Object summary */ ALE_ACT, /* Action summary */ @@ -311,7 +310,7 @@ void ipo_rainbow(int cur, int tot, float *out); /* ------------- NLA-Mapping ----------------------- */ /* anim_draw.c */ -// XXX these are soon to be depreceated? +// XXX these need attention for the new editing method... /* Obtain the Object providing NLA-scaling for the given channel if applicable */ struct Object *ANIM_nla_mapping_get(bAnimContext *ac, bAnimListElem *ale); diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index 27be82ccec0..b2f4751fa25 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -307,11 +307,11 @@ static int actkeys_copy_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void ACT_OT_keyframes_copy (wmOperatorType *ot) +void ACT_OT_copy (wmOperatorType *ot) { /* identifiers */ ot->name= "Copy Keyframes"; - ot->idname= "ACT_OT_keyframes_copy"; + ot->idname= "ACT_OT_copy"; /* api callbacks */ ot->exec= actkeys_copy_exec; @@ -351,11 +351,11 @@ static int actkeys_paste_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void ACT_OT_keyframes_paste (wmOperatorType *ot) +void ACT_OT_paste (wmOperatorType *ot) { /* identifiers */ ot->name= "Paste Keyframes"; - ot->idname= "ACT_OT_keyframes_paste"; + ot->idname= "ACT_OT_paste"; /* api callbacks */ ot->exec= actkeys_paste_exec; @@ -447,11 +447,11 @@ static int actkeys_insertkey_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void ACT_OT_keyframes_insert (wmOperatorType *ot) +void ACT_OT_insert (wmOperatorType *ot) { /* identifiers */ ot->name= "Insert Keyframes"; - ot->idname= "ACT_OT_keyframes_insert"; + ot->idname= "ACT_OT_insert"; /* api callbacks */ ot->invoke= WM_menu_invoke; @@ -524,11 +524,11 @@ static int actkeys_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_FINISHED; } -void ACT_OT_keyframes_duplicate (wmOperatorType *ot) +void ACT_OT_duplicate (wmOperatorType *ot) { /* identifiers */ ot->name= "Duplicate Keyframes"; - ot->idname= "ACT_OT_keyframes_duplicate"; + ot->idname= "ACT_OT_duplicate"; /* api callbacks */ ot->invoke= actkeys_duplicate_invoke; @@ -591,11 +591,11 @@ static int actkeys_delete_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void ACT_OT_keyframes_delete (wmOperatorType *ot) +void ACT_OT_delete (wmOperatorType *ot) { /* identifiers */ ot->name= "Delete Keyframes"; - ot->idname= "ACT_OT_keyframes_delete"; + ot->idname= "ACT_OT_delete"; /* api callbacks */ ot->invoke= WM_operator_confirm; @@ -654,11 +654,11 @@ static int actkeys_clean_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void ACT_OT_keyframes_clean (wmOperatorType *ot) +void ACT_OT_clean (wmOperatorType *ot) { /* identifiers */ ot->name= "Clean Keyframes"; - ot->idname= "ACT_OT_keyframes_clean"; + ot->idname= "ACT_OT_clean"; /* api callbacks */ //ot->invoke= // XXX we need that number popup for this! @@ -778,11 +778,11 @@ static int actkeys_sample_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void ACT_OT_keyframes_sample (wmOperatorType *ot) +void ACT_OT_sample (wmOperatorType *ot) { /* identifiers */ ot->name= "Sample Keyframes"; - ot->idname= "ACT_OT_keyframes_sample"; + ot->idname= "ACT_OT_sample"; /* api callbacks */ ot->exec= actkeys_sample_exec; @@ -853,11 +853,11 @@ static int actkeys_expo_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void ACT_OT_keyframes_extrapolation_type_set (wmOperatorType *ot) +void ACT_OT_extrapolation_type_set (wmOperatorType *ot) { /* identifiers */ ot->name= "Set Keyframe Extrapolation"; - ot->idname= "ACT_OT_keyframes_extrapolation_type_set"; + ot->idname= "ACT_OT_extrapolation_type_set"; /* api callbacks */ ot->invoke= WM_menu_invoke; @@ -923,11 +923,11 @@ static int actkeys_ipo_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void ACT_OT_keyframes_interpolation_type (wmOperatorType *ot) +void ACT_OT_interpolation_type_set (wmOperatorType *ot) { /* identifiers */ ot->name= "Set Keyframe Interpolation"; - ot->idname= "ACT_OT_keyframes_interpolation_type"; + ot->idname= "ACT_OT_interpolation_type_set"; /* api callbacks */ ot->invoke= WM_menu_invoke; @@ -1011,11 +1011,11 @@ static int actkeys_handletype_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void ACT_OT_keyframes_handle_type_set (wmOperatorType *ot) +void ACT_OT_handle_type_set (wmOperatorType *ot) { /* identifiers */ ot->name= "Set Keyframe Handle Type"; - ot->idname= "ACT_OT_keyframes_handle_type_set"; + ot->idname= "ACT_OT_handle_type_set"; /* api callbacks */ ot->invoke= WM_menu_invoke; @@ -1032,10 +1032,10 @@ void ACT_OT_keyframes_handle_type_set (wmOperatorType *ot) /* ************************************************************************** */ /* TRANSFORM STUFF */ -/* ***************** Snap Current Frame Operator *********************** */ +/* ***************** Jump to Selected Frames Operator *********************** */ /* snap current-frame indicator to 'average time' of selected keyframe */ -static int actkeys_cfrasnap_exec(bContext *C, wmOperator *op) +static int actkeys_framejump_exec(bContext *C, wmOperator *op) { bAnimContext ac; ListBase anim_data= {NULL, NULL}; @@ -1071,14 +1071,14 @@ static int actkeys_cfrasnap_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void ACT_OT_keyframes_cfrasnap (wmOperatorType *ot) +void ACT_OT_frame_jump (wmOperatorType *ot) { /* identifiers */ - ot->name= "Snap Current Frame to Keys"; - ot->idname= "ACT_OT_keyframes_cfrasnap"; + ot->name= "Jump to Frame"; + ot->idname= "ACT_OT_frame_jump"; /* api callbacks */ - ot->exec= actkeys_cfrasnap_exec; + ot->exec= actkeys_framejump_exec; ot->poll= ED_operator_action_active; /* flags */ @@ -1166,11 +1166,11 @@ static int actkeys_snap_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void ACT_OT_keyframes_snap (wmOperatorType *ot) +void ACT_OT_snap (wmOperatorType *ot) { /* identifiers */ ot->name= "Snap Keys"; - ot->idname= "ACT_OT_keyframes_snap"; + ot->idname= "ACT_OT_snap"; /* api callbacks */ ot->invoke= WM_menu_invoke; @@ -1282,11 +1282,11 @@ static int actkeys_mirror_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void ACT_OT_keyframes_mirror (wmOperatorType *ot) +void ACT_OT_mirror (wmOperatorType *ot) { /* identifiers */ ot->name= "Mirror Keys"; - ot->idname= "ACT_OT_keyframes_mirror"; + ot->idname= "ACT_OT_mirror"; /* api callbacks */ ot->invoke= WM_menu_invoke; diff --git a/source/blender/editors/space_action/action_header.c b/source/blender/editors/space_action/action_header.c index fa96e1ea81f..1bc30b2ac42 100644 --- a/source/blender/editors/space_action/action_header.c +++ b/source/blender/editors/space_action/action_header.c @@ -51,11 +51,14 @@ #include "ED_types.h" #include "ED_util.h" +#include "RNA_access.h" + #include "WM_api.h" #include "WM_types.h" #include "BIF_gl.h" #include "BIF_glutil.h" +#include "BIF_transform.h" #include "UI_interface.h" #include "UI_resources.h" @@ -63,1494 +66,183 @@ #include "action_intern.h" +enum { + B_REDR= 0, +} eActHeader_Events; + /* ********************************************************* */ /* Menu Defines... */ -/* button events */ -enum { - B_REDR = 0, - B_ACTCOPYKEYS, - B_ACTPASTEKEYS, -} eActHeader_ButEvents; - -/* ------------------------------- */ -/* enums declaring constants that are used as menu event codes */ - -enum { - ACTMENU_VIEW_CENTERVIEW= 0, - ACTMENU_VIEW_AUTOUPDATE, - ACTMENU_VIEW_PLAY3D, - ACTMENU_VIEW_PLAYALL, - ACTMENU_VIEW_ALL, - ACTMENU_VIEW_MAXIMIZE, - ACTMENU_VIEW_LOCK, - ACTMENU_VIEW_SLIDERS, - ACTMENU_VIEW_NEXTMARKER, - ACTMENU_VIEW_PREVMARKER, - ACTMENU_VIEW_NEXTKEYFRAME, - ACTMENU_VIEW_PREVKEYFRAME, - ACTMENU_VIEW_TIME, - ACTMENU_VIEW_NOHIDE, - ACTMENU_VIEW_FRANUM, - ACTMENU_VIEW_TRANSDELDUPS, - ACTMENU_VIEW_HORIZOPTIMISE, - ACTMENU_VIEW_GCOLORS, - ACTMENU_VIEW_PREVRANGESET, - ACTMENU_VIEW_PREVRANGECLEAR, - ACTMENU_VIEW_PREVRANGEAUTO -}; - -enum { - ACTMENU_SEL_BORDER = 0, - ACTMENU_SEL_BORDERC, - ACTMENU_SEL_BORDERM, - ACTMENU_SEL_ALL_KEYS, - ACTMENU_SEL_ALL_CHAN, - ACTMENU_SEL_ALL_MARKERS, - ACTMENU_SEL_INVERSE_KEYS, - ACTMENU_SEL_INVERSE_MARKERS, - ACTMENU_SEL_INVERSE_CHANNELS, - ACTMENU_SEL_LEFTKEYS, - ACTMENU_SEL_RIGHTKEYS -}; - -enum { - ACTMENU_SEL_COLUMN_KEYS = 1, - ACTMENU_SEL_COLUMN_CFRA, - ACTMENU_SEL_COLUMN_MARKERSCOLUMN, - ACTMENU_SEL_COLUMN_MARKERSBETWEEN -}; - -enum { - ACTMENU_CHANNELS_OPENLEVELS = 0, - ACTMENU_CHANNELS_CLOSELEVELS, - ACTMENU_CHANNELS_EXPANDALL, - ACTMENU_CHANNELS_SHOWACHANS, - ACTMENU_CHANNELS_DELETE -}; - -enum { - ACTMENU_CHANNELS_CHANPOS_MOVE_CHANNEL_UP = 0, - ACTMENU_CHANNELS_CHANPOS_MOVE_CHANNEL_DOWN, - ACTMENU_CHANNELS_CHANPOS_MOVE_CHANNEL_TOP, - ACTMENU_CHANNELS_CHANPOS_MOVE_CHANNEL_BOTTOM -}; - -enum { - ACTMENU_CHANNELS_GROUP_ADD_TOACTIVE = 0, - ACTMENU_CHANNELS_GROUP_ADD_TONEW, - ACTMENU_CHANNELS_GROUP_REMOVE, - ACTMENU_CHANNELS_GROUP_SYNCPOSE -}; - -enum { - ACTMENU_CHANNELS_SETTINGS_TOGGLE = 0, - ACTMENU_CHANNELS_SETTINGS_ENABLE, - ACTMENU_CHANNELS_SETTINGS_DISABLE, -}; - -enum { - ACTMENU_KEY_DUPLICATE = 0, - ACTMENU_KEY_DELETE, - ACTMENU_KEY_CLEAN, - ACTMENU_KEY_SAMPLEKEYS, - ACTMENU_KEY_INSERTKEY -}; - -enum { - ACTMENU_KEY_TRANSFORM_MOVE = 0, - ACTMENU_KEY_TRANSFORM_SCALE, - ACTMENU_KEY_TRANSFORM_SLIDE, - ACTMENU_KEY_TRANSFORM_EXTEND -}; - -enum { - ACTMENU_KEY_HANDLE_AUTO = 0, - ACTMENU_KEY_HANDLE_ALIGN, - ACTMENU_KEY_HANDLE_FREE, - ACTMENU_KEY_HANDLE_VECTOR -}; - -enum { - ACTMENU_KEY_INTERP_CONST = 0, - ACTMENU_KEY_INTERP_LINEAR, - ACTMENU_KEY_INTERP_BEZIER -}; - -enum { - ACTMENU_KEY_EXTEND_CONST = 0, - ACTMENU_KEY_EXTEND_EXTRAPOLATION, - ACTMENU_KEY_EXTEND_CYCLIC, - ACTMENU_KEY_EXTEND_CYCLICEXTRAPOLATION -}; - -enum { - ACTMENU_KEY_SNAP_NEARFRAME = 1, - ACTMENU_KEY_SNAP_CURFRAME, - ACTMENU_KEY_SNAP_NEARMARK, - ACTMENU_KEY_SNAP_NEARTIME, - ACTMENU_KEY_SNAP_CFRA2KEY, -}; - -enum { - ACTMENU_KEY_MIRROR_CURFRAME = 1, - ACTMENU_KEY_MIRROR_YAXIS, - ACTMENU_KEY_MIRROR_XAXIS, - ACTMENU_KEY_MIRROR_MARKER -}; - -enum { - ACTMENU_MARKERS_ADD = 0, - ACTMENU_MARKERS_DUPLICATE, - ACTMENU_MARKERS_DELETE, - ACTMENU_MARKERS_NAME, - ACTMENU_MARKERS_MOVE, - ACTMENU_MARKERS_LOCALADD, - ACTMENU_MARKERS_LOCALRENAME, - ACTMENU_MARKERS_LOCALDELETE, - ACTMENU_MARKERS_LOCALMOVE -}; - -/* ------------------------------- */ -/* macros for easier state testing (only for use here) */ - -/* test if active action editor is showing any markers */ -#if 0 - #define SACTION_HASMARKERS \ - ((saction->action && saction->action->markers.first) \ - || (scene->markers.first)) -#endif - -/* need to find out how to get scene from context */ -#define SACTION_HASMARKERS (saction->action && saction->action->markers.first) - -/* ------------------------------- */ - -/* *************************************************************** */ -/* menus */ - -/* Key menu --------------------------- */ - -static void do_keymenu_transformmenu(bContext *C, void *arg, int event) +static void act_viewmenu(bContext *C, uiLayout *layout, void *arg_unused) { - switch (event) - { - case ACTMENU_KEY_TRANSFORM_MOVE: - //transform_action_keys('g', 0); - break; - case ACTMENU_KEY_TRANSFORM_SCALE: - //transform_action_keys('s', 0); - break; - case ACTMENU_KEY_TRANSFORM_SLIDE: - //transform_action_keys('t', 0); - break; - case ACTMENU_KEY_TRANSFORM_EXTEND: - //transform_action_keys('e', 0); - break; - } -} - -static uiBlock *action_keymenu_transformmenu(bContext *C, ARegion *ar, void *arg_unused) -{ - uiBlock *block; - short yco= 0, menuwidth=120; + bScreen *sc= CTX_wm_screen(C); + ScrArea *sa= CTX_wm_area(C); + SpaceAction *sact= (SpaceAction*)CTX_wm_space_data(C); + PointerRNA spaceptr; - block= uiBeginBlock(C, ar, "action_keymenu_transformmenu", UI_EMBOSSP); - uiBlockSetButmFunc(block, do_keymenu_transformmenu, NULL); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Grab/Move|G", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_KEY_TRANSFORM_MOVE, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Grab/Extend from Frame|E", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_KEY_TRANSFORM_EXTEND, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Scale|S", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_KEY_TRANSFORM_SCALE, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Time Slide|T", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_KEY_TRANSFORM_SLIDE, ""); + /* retrieve state */ + RNA_pointer_create(&sc->id, &RNA_SpaceDopeSheetEditor, sact, &spaceptr); - uiBlockSetDirection(block, UI_RIGHT); + /* create menu */ + //uiItemO(layout, NULL, ICON_MENU_PANEL, "ACT_OT_properties"); - uiTextBoundsBlock(block, 60); - uiEndBlock(C, block); + //uiItemS(layout); - return block; -} - -static void do_keymenu_snapmenu(bContext *C, void *arg, int event) -{ - switch(event) - { - case ACTMENU_KEY_SNAP_NEARFRAME: - case ACTMENU_KEY_SNAP_CURFRAME: - case ACTMENU_KEY_SNAP_NEARMARK: - case ACTMENU_KEY_SNAP_NEARTIME: - //snap_action_keys(event); - break; - - case ACTMENU_KEY_SNAP_CFRA2KEY: - //snap_cfra_action(); - break; - } -} - -static uiBlock *action_keymenu_snapmenu(bContext *C, ARegion *ar, void *arg_unused) -{ - SpaceAction *saction= (SpaceAction*)CTX_wm_space_data(C); - uiBlock *block; - short yco= 0, menuwidth=120; - + uiItemR(layout, NULL, 0, &spaceptr, "show_cframe_indicator", 0, 0, 0); + uiItemR(layout, NULL, 0, &spaceptr, "show_sliders", 0, 0, 0); + uiItemR(layout, NULL, 0, &spaceptr, "automerge_keyframes", 0, 0, 0); - block= uiBeginBlock(C, ar, "action_keymenu_snapmenu", UI_EMBOSSP); - uiBlockSetButmFunc(block, do_keymenu_snapmenu, NULL); - - if (saction->flag & SACTION_DRAWTIME) { - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Key -> Nearest Second|Shift S, 1", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_KEY_SNAP_NEARTIME, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Key -> Current Time|Shift S, 2", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_KEY_SNAP_CURFRAME, ""); - - } - else { - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Key -> Nearest Frame|Shift S, 1", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_KEY_SNAP_NEARFRAME, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Key -> Current Frame|Shift S, 2", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_KEY_SNAP_CURFRAME, ""); - } - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Key -> Nearest Marker|Shift S, 3", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_KEY_SNAP_NEARMARK, ""); - - uiDefBut(block, SEPR, 0, "", 0, yco-=6, - menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Current Frame -> Key|Ctrl Shift S", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_KEY_SNAP_NEARMARK, ""); + if (sact->flag & SACTION_DRAWTIME) + uiItemO(layout, "Show Frames", 0, "ANIM_OT_time_toggle"); + else + uiItemO(layout, "Show Seconds", 0, "ANIM_OT_time_toggle"); - uiBlockSetDirection(block, UI_RIGHT); + uiItemS(layout); - uiTextBoundsBlock(block, 60); - uiEndBlock(C, block); + uiItemO(layout, NULL, 0, "ANIM_OT_previewrange_set"); + uiItemO(layout, NULL, 0, "ANIM_OT_previewrange_clear"); - return block; -} - -static void do_keymenu_mirrormenu(bContext *C, void *arg, int event) -{ - switch(event) - { - case ACTMENU_KEY_MIRROR_CURFRAME: - case ACTMENU_KEY_MIRROR_YAXIS: - //mirror_action_keys(event); - break; - } - -} - -static uiBlock *action_keymenu_mirrormenu(bContext *C, ARegion *ar, void *arg_unused) -{ - uiBlock *block; - short yco= 0, menuwidth=120; + uiItemO(layout, NULL, 0, "ACT_OT_previewrange_set"); - block= uiBeginBlock(C, ar, "action_keymenu_mirrormenu", UI_EMBOSSP); - uiBlockSetButmFunc(block, do_keymenu_mirrormenu, NULL); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Current Frame|Shift M, 1", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_KEY_MIRROR_CURFRAME, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Vertical Axis|Shift M, 2", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_KEY_MIRROR_YAXIS, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Horizontal Axis|Shift M, 3", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_KEY_MIRROR_XAXIS, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Selected Marker|Shift M, 4", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_KEY_MIRROR_MARKER, ""); + uiItemS(layout); - uiBlockSetDirection(block, UI_RIGHT); + uiItemO(layout, NULL, 0, "ACT_OT_frame_jump"); - uiTextBoundsBlock(block, 60); - uiEndBlock(C, block); + uiItemO(layout, NULL, 0, "ACT_OT_view_all"); - return block; -} - -static void do_keymenu_handlemenu(bContext *C, void *arg, int event) -{ - switch (event) { - case ACTMENU_KEY_HANDLE_AUTO: - //sethandles_action_keys(HD_AUTO); - break; - - case ACTMENU_KEY_HANDLE_ALIGN: - case ACTMENU_KEY_HANDLE_FREE: - /* OK, this is kinda dumb, need to fix the - * toggle crap in sethandles_ipo_keys() - */ - //sethandles_action_keys(HD_ALIGN); - break; - - case ACTMENU_KEY_HANDLE_VECTOR: - //sethandles_action_keys(HD_VECT); - break; - } -} - -static uiBlock *action_keymenu_handlemenu(bContext *C, ARegion *ar, void *arg_unused) -{ - uiBlock *block; - short yco= 0, menuwidth=120; - - block= uiBeginBlock(C, ar, "action_keymenu_handlemenu", UI_EMBOSSP); - uiBlockSetButmFunc(block, do_keymenu_handlemenu, NULL); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Auto|Shift H", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_KEY_HANDLE_AUTO, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Aligned|H", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_KEY_HANDLE_ALIGN, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Free|H", 0, yco-=20, menuwidth, - 19, NULL, 0.0, 0.0, 0, - ACTMENU_KEY_HANDLE_FREE, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Vector|V", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_KEY_HANDLE_VECTOR, ""); - - uiBlockSetDirection(block, UI_RIGHT); - - uiTextBoundsBlock(block, 60); - uiEndBlock(C, block); - - return block; -} - -static void do_keymenu_extendmenu(bContext *C, void *arg, int event) -{ - switch(event) - { - case ACTMENU_KEY_EXTEND_CONST: - //action_set_ipo_flags(SET_EXTEND_MENU, SET_EXTEND_CONSTANT); - break; - case ACTMENU_KEY_EXTEND_EXTRAPOLATION: - //action_set_ipo_flags(SET_EXTEND_MENU, SET_EXTEND_EXTRAPOLATION); - break; - case ACTMENU_KEY_EXTEND_CYCLIC: - //action_set_ipo_flags(SET_EXTEND_MENU, SET_EXTEND_CYCLIC); - break; - case ACTMENU_KEY_EXTEND_CYCLICEXTRAPOLATION: - //action_set_ipo_flags(SET_EXTEND_MENU, SET_EXTEND_CYCLICEXTRAPOLATION); - break; - } -} - -static uiBlock *action_keymenu_extendmenu(bContext *C, ARegion *ar, void *arg_unused) -{ - uiBlock *block; - short yco= 0, menuwidth=120; - - block= uiBeginBlock(C, ar, "action_keymenu_extendmenu", UI_EMBOSSP); - uiBlockSetButmFunc(block, do_keymenu_extendmenu, NULL); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Constant", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_KEY_EXTEND_CONST, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Extrapolation", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_KEY_EXTEND_EXTRAPOLATION, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Cyclic", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_KEY_EXTEND_CYCLIC, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Cyclic Extrapolation", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_KEY_EXTEND_CYCLICEXTRAPOLATION, ""); - - uiBlockSetDirection(block, UI_RIGHT); - - uiTextBoundsBlock(block, 60); - uiEndBlock(C, block); - - return block; -} - -static void do_keymenu_intpolmenu(bContext *C, void *arg, int event) -{ - switch(event) - { - case ACTMENU_KEY_INTERP_CONST: - //action_set_ipo_flags(SET_IPO_MENU, SET_IPO_CONSTANT); - break; - case ACTMENU_KEY_INTERP_LINEAR: - //action_set_ipo_flags(SET_IPO_MENU, SET_IPO_LINEAR); - break; - case ACTMENU_KEY_INTERP_BEZIER: - //action_set_ipo_flags(SET_IPO_MENU, SET_IPO_BEZIER); - break; - } -} - -static uiBlock *action_keymenu_intpolmenu(bContext *C, ARegion *ar, void *arg_unused) -{ - uiBlock *block; - short yco= 0, menuwidth=120; - - block= uiBeginBlock(C, ar, "action_keymenu_intpolmenu", UI_EMBOSSP); - uiBlockSetButmFunc(block, do_keymenu_intpolmenu, NULL); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Constant|Shift T, 1", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_KEY_INTERP_CONST, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Linear|Shift T, 2", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_KEY_INTERP_LINEAR, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Bezier|Shift T, 3", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_KEY_INTERP_BEZIER, ""); - - uiBlockSetDirection(block, UI_RIGHT); - - uiTextBoundsBlock(block, 60); - uiEndBlock(C, block); - - return block; -} - -static void do_action_keymenu(bContext *C, void *arg, int event) -{ - SpaceAction *saction= (SpaceAction*)CTX_wm_space_data(C); - bAction *act; - //Key *key; - - if (!saction) return; - - act = saction->action; - //key = get_action_mesh_key(); - - switch(event) - { - case ACTMENU_KEY_DUPLICATE: - //duplicate_action_keys(); - break; - case ACTMENU_KEY_DELETE: - //delete_action_keys(); - break; - case ACTMENU_KEY_CLEAN: - //clean_action(); - break; - case ACTMENU_KEY_SAMPLEKEYS: - //sample_action_keys(); - break; - case ACTMENU_KEY_INSERTKEY: - //insertkey_action(); - break; - } -} - -static uiBlock *action_keymenu(bContext *C, ARegion *ar, void *arg_unused) -{ - ScrArea *curarea= CTX_wm_area(C); - uiBlock *block; - short yco= 0, menuwidth=120; - - block= uiBeginBlock(C, ar, "action_keymenu", UI_EMBOSSP); - - - uiBlockSetButmFunc(block, do_action_keymenu, NULL); - - uiDefIconTextBlockBut(block, action_keymenu_transformmenu, - NULL, ICON_RIGHTARROW_THIN, "Transform", 0, yco-=20, 120, 20, ""); - - uiDefIconTextBlockBut(block, action_keymenu_snapmenu, - NULL, ICON_RIGHTARROW_THIN, "Snap", 0, yco-=20, 120, 20, ""); - - uiDefIconTextBlockBut(block, action_keymenu_mirrormenu, - NULL, ICON_RIGHTARROW_THIN, "Mirror", 0, yco-=20, 120, 20, ""); - - uiDefBut(block, SEPR, 0, "", 0, yco-=6, - menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Insert Key|I", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_KEY_INSERTKEY, ""); - - uiDefBut(block, SEPR, 0, "", 0, yco-=6, - menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Duplicate|Shift D", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_KEY_DUPLICATE, ""); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Delete|X", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_KEY_DELETE, ""); - - uiDefBut(block, SEPR, 0, "", 0, yco-=6, - menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Clean Action|O", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_KEY_CLEAN, ""); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Sample Keys|Alt O", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_KEY_SAMPLEKEYS, ""); - - uiDefBut(block, SEPR, 0, "", 0, yco-=6, - menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - - uiDefIconTextBlockBut(block, action_keymenu_handlemenu, - NULL, ICON_RIGHTARROW_THIN, - "Handle Type", 0, yco-=20, 120, 20, ""); - - uiDefBut(block, SEPR, 0, "", 0, yco-=6, - menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - - uiDefIconTextBlockBut(block, action_keymenu_extendmenu, - NULL, ICON_RIGHTARROW_THIN, - "Extend Mode", 0, yco-=20, 120, 20, ""); - uiDefIconTextBlockBut(block, action_keymenu_intpolmenu, - NULL, ICON_RIGHTARROW_THIN, - "Interpolation Mode", 0, yco-=20, 120, 20, ""); - - if(curarea->headertype==HEADERTOP) { - uiBlockSetDirection(block, UI_DOWN); - } - else { - uiBlockSetDirection(block, UI_TOP); - uiBlockFlipOrder(block); - } - - uiTextBoundsBlock(block, 50); - uiEndBlock(C, block); - - return block; -} - -/* Frame menu --------------------------- */ - - -// framemenu uses functions from keymenu -static uiBlock *action_framemenu(bContext *C, ARegion *ar, void *arg_unused) -{ - ScrArea *curarea= CTX_wm_area(C); - uiBlock *block; - short yco= 0, menuwidth=120; - - block= uiBeginBlock(C, ar, "action_framemenu", UI_EMBOSSP); - uiBlockSetButmFunc(block, do_action_keymenu, NULL); - - uiDefIconTextBlockBut(block, action_keymenu_transformmenu, - NULL, ICON_RIGHTARROW_THIN, "Transform", 0, yco-=20, 120, 20, ""); - - uiDefIconTextBlockBut(block, action_keymenu_snapmenu, - NULL, ICON_RIGHTARROW_THIN, "Snap", 0, yco-=20, 120, 20, ""); - - uiDefIconTextBlockBut(block, action_keymenu_mirrormenu, - NULL, ICON_RIGHTARROW_THIN, "Mirror", 0, yco-=20, 120, 20, ""); - - uiDefBut(block, SEPR, 0, "", 0, yco-=6, - menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Duplicate|Shift D", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_KEY_DUPLICATE, ""); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Delete|X", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_KEY_DELETE, ""); - - if(curarea->headertype==HEADERTOP) { - uiBlockSetDirection(block, UI_DOWN); - } - else { - uiBlockSetDirection(block, UI_TOP); - uiBlockFlipOrder(block); - } - - uiTextBoundsBlock(block, 50); - uiEndBlock(C, block); - - return block; -} - -/* Marker menu --------------------------- */ - -static void do_markermenu(bContext *C, void *arg, int event) -{ - switch(event) - { - case ACTMENU_MARKERS_ADD: - //add_marker(CFRA); - break; - case ACTMENU_MARKERS_DUPLICATE: - //duplicate_marker(); - break; - case ACTMENU_MARKERS_DELETE: - //remove_marker(); - break; - case ACTMENU_MARKERS_NAME: - //rename_marker(); - break; - case ACTMENU_MARKERS_MOVE: - //transform_markers('g', 0); - break; - case ACTMENU_MARKERS_LOCALADD: - //action_add_localmarker(G.saction->action, CFRA); - break; - case ACTMENU_MARKERS_LOCALDELETE: - //action_remove_localmarkers(G.saction->action); - break; - case ACTMENU_MARKERS_LOCALRENAME: - //action_rename_localmarker(G.saction->action); - break; - case ACTMENU_MARKERS_LOCALMOVE: - /*G.saction->flag |= SACTION_POSEMARKERS_MOVE; - transform_markers('g', 0); - G.saction->flag &= ~SACTION_POSEMARKERS_MOVE;*/ - break; - } -} - -static uiBlock *action_markermenu(bContext *C, ARegion *ar, void *arg_unused) -{ - SpaceAction *saction= (SpaceAction*)CTX_wm_space_data(C); - ScrArea *curarea= CTX_wm_area(C); - uiBlock *block; - short yco= 0, menuwidth=120; - - block= uiBeginBlock(C, ar, "action_markermenu", UI_EMBOSSP); - uiBlockSetButmFunc(block, do_markermenu, NULL); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Add Marker|M", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 1, ACTMENU_MARKERS_ADD, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Duplicate Marker|Ctrl Shift D", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 1, ACTMENU_MARKERS_DUPLICATE, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Delete Marker|Shift X", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 1, ACTMENU_MARKERS_DELETE, ""); - - uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "(Re)Name Marker|Ctrl M", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 1, ACTMENU_MARKERS_NAME, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Grab/Move Marker|Ctrl G", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 1, ACTMENU_MARKERS_MOVE, ""); - - if (saction->mode == SACTCONT_ACTION) { - uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Add Pose Marker|Shift L", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 1, ACTMENU_MARKERS_LOCALADD, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Rename Pose Marker|Ctrl Shift L", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 1, ACTMENU_MARKERS_LOCALRENAME, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Delete Pose Marker|Alt L", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 1, ACTMENU_MARKERS_LOCALDELETE, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Grab/Move Pose Marker|Ctrl L", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 1, ACTMENU_MARKERS_LOCALMOVE, ""); - } - - if(curarea->headertype==HEADERTOP) { - uiBlockSetDirection(block, UI_DOWN); - } - else { - uiBlockSetDirection(block, UI_TOP); - uiBlockFlipOrder(block); - } - - uiTextBoundsBlock(block, 50); - uiEndBlock(C, block); - - return block; -} - - -/* Channel menu --------------------------- */ - -static void do_channelmenu_posmenu(bContext *C, void *arg, int event) -{ - switch(event) - { - case ACTMENU_CHANNELS_CHANPOS_MOVE_CHANNEL_DOWN: - //rearrange_action_channels(REARRANGE_ACTCHAN_DOWN); - break; - case ACTMENU_CHANNELS_CHANPOS_MOVE_CHANNEL_UP: - //rearrange_action_channels(REARRANGE_ACTCHAN_UP); - break; - case ACTMENU_CHANNELS_CHANPOS_MOVE_CHANNEL_TOP: - //rearrange_action_channels(REARRANGE_ACTCHAN_TOP); - break; - case ACTMENU_CHANNELS_CHANPOS_MOVE_CHANNEL_BOTTOM: - //rearrange_action_channels(REARRANGE_ACTCHAN_BOTTOM); - break; - } -} - -static uiBlock *action_channelmenu_posmenu(bContext *C, ARegion *ar, void *arg_unused) -{ - uiBlock *block; - short yco= 0, menuwidth=120; - - block= uiBeginBlock(C, ar, "action_channelmenu_posmenu", UI_EMBOSSP); - uiBlockSetButmFunc(block, do_channelmenu_posmenu, NULL); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Move Up|Shift Page Up", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_CHANNELS_CHANPOS_MOVE_CHANNEL_UP, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Move Down|Shift Page Down", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_CHANNELS_CHANPOS_MOVE_CHANNEL_DOWN, ""); - - uiDefBut(block, SEPR, 0, "", 0, yco-=6, - menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Move to Top|Ctrl Shift Page Up", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_CHANNELS_CHANPOS_MOVE_CHANNEL_TOP, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Move to Bottom|Ctrl Shift Page Down", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_CHANNELS_CHANPOS_MOVE_CHANNEL_BOTTOM, ""); - - uiBlockSetDirection(block, UI_RIGHT); - uiTextBoundsBlock(block, 60); - - return block; -} - -static void do_channelmenu_groupmenu(bContext *C, void *arg, int event) -{ - switch(event) - { - case ACTMENU_CHANNELS_GROUP_ADD_TOACTIVE: - //action_groups_group(0); - break; - case ACTMENU_CHANNELS_GROUP_ADD_TONEW: - //action_groups_group(1); - break; - case ACTMENU_CHANNELS_GROUP_REMOVE: - //action_groups_ungroup(); - break; - case ACTMENU_CHANNELS_GROUP_SYNCPOSE: /* Syncronise Pose-data and Action-data */ - //sync_pchan2achan_grouping(); - break; - } -} - -static uiBlock *action_channelmenu_groupmenu(bContext *C, ARegion *ar, void *arg_unused) -{ - uiBlock *block; - short yco= 0, menuwidth=120; - - block= uiBeginBlock(C, ar, "action_channelmenu_groupmenu", UI_EMBOSSP); - uiBlockSetButmFunc(block, do_channelmenu_groupmenu, NULL); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Add to Active Group|Shift G", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_CHANNELS_GROUP_ADD_TOACTIVE, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Add to New Group|Ctrl Shift G", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_CHANNELS_GROUP_ADD_TONEW, ""); - - uiDefBut(block, SEPR, 0, "", 0, yco-=6, - menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Remove From Group|Alt G", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_CHANNELS_GROUP_REMOVE, ""); - - uiDefBut(block, SEPR, 0, "", 0, yco-=6, - menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Synchronise with Armature", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_CHANNELS_GROUP_SYNCPOSE, ""); - - uiBlockSetDirection(block, UI_RIGHT); - uiTextBoundsBlock(block, 60); - - return block; -} - -static void do_channelmenu_settingsmenu(bContext *C, void *arg, int event) -{ - //setflag_action_channels(event); -} - -static uiBlock *action_channelmenu_settingsmenu(bContext *C, ARegion *ar, void *arg_unused) -{ - uiBlock *block; - short yco= 0, menuwidth=120; - - block= uiBeginBlock(C, ar, "action_channelmenu_settingsmenu", UI_EMBOSSP); - uiBlockSetButmFunc(block, do_channelmenu_settingsmenu, NULL); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Toggle a Setting|Shift W", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_CHANNELS_SETTINGS_TOGGLE, ""); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Enable a Setting|Ctrl Shift W", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_CHANNELS_SETTINGS_ENABLE, ""); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Disable a Setting|Alt W", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_CHANNELS_SETTINGS_DISABLE, ""); - - uiBlockSetDirection(block, UI_RIGHT); - uiTextBoundsBlock(block, 60); - - return block; -} - -static void do_channelmenu(bContext *C, void *arg, int event) -{ - SpaceAction *saction= (SpaceAction*)CTX_wm_space_data(C); - - if (saction == NULL) return; - - switch(event) - { - case ACTMENU_CHANNELS_OPENLEVELS: /* Unfold selected channels one step */ - //openclose_level_action(1); - break; - case ACTMENU_CHANNELS_CLOSELEVELS: /* Fold selected channels one step */ - //openclose_level_action(-1); - break; - case ACTMENU_CHANNELS_EXPANDALL: /* Expands all channels */ - //expand_all_action(); - break; - case ACTMENU_CHANNELS_SHOWACHANS: /* Unfold groups that are hiding selected achans */ - //expand_obscuregroups_action(); - break; - case ACTMENU_CHANNELS_DELETE: /* Deletes selected channels */ - //delete_action_channels(); - break; - } -} - -static uiBlock *action_channelmenu(bContext *C, ARegion *ar, void *arg_unused) -{ - ScrArea *curarea= CTX_wm_area(C); - uiBlock *block; - short yco= 0, menuwidth=120; - - block= uiBeginBlock(C, ar, "action_channelmenu", UI_EMBOSSP); - uiBlockSetButmFunc(block, do_channelmenu, NULL); - - uiDefIconTextBlockBut(block, action_channelmenu_groupmenu, - NULL, ICON_RIGHTARROW_THIN, - "Grouping", 0, yco-=20, 120, 20, ""); - - uiDefIconTextBlockBut(block, action_channelmenu_posmenu, - NULL, ICON_RIGHTARROW_THIN, - "Ordering", 0, yco-=20, 120, 20, ""); - - uiDefIconTextBlockBut(block, action_channelmenu_settingsmenu, - NULL, ICON_RIGHTARROW_THIN, - "Settings", 0, yco-=20, 120, 20, ""); - - uiDefBut(block, SEPR, 0, "", 0, yco-=6, - menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Delete|X", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_CHANNELS_DELETE, ""); - - uiDefBut(block, SEPR, 0, "", 0, yco-=6, - menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Toggle Show Hierachy|~", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_CHANNELS_EXPANDALL, ""); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Show Group-Hidden Channels|Shift ~", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_CHANNELS_SHOWACHANS, ""); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Expand One Level|Ctrl NumPad+", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_CHANNELS_OPENLEVELS, ""); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Collapse One Level|Ctrl NumPad-", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_CHANNELS_CLOSELEVELS, ""); - - if(curarea->headertype==HEADERTOP) { - uiBlockSetDirection(block, UI_DOWN); - } - else { - uiBlockSetDirection(block, UI_TOP); - uiBlockFlipOrder(block); - } - - uiTextBoundsBlock(block, 50); - uiEndBlock(C, block); - - return block; -} - -/* Grease Pencil --------------------------- */ - -/* Uses channelmenu functions */ -static uiBlock *action_gplayermenu(bContext *C, ARegion *ar, void *arg_unused) -{ - ScrArea *curarea= CTX_wm_area(C); - uiBlock *block; - short yco= 0, menuwidth=120; - - block= uiBeginBlock(C, ar, "action_gplayermenu", UI_EMBOSSP); - uiBlockSetButmFunc(block, do_channelmenu, NULL); - - uiDefIconTextBlockBut(block, action_channelmenu_settingsmenu, - NULL, ICON_RIGHTARROW_THIN, - "Settings", 0, yco-=20, 120, 20, ""); - - uiDefBut(block, SEPR, 0, "", 0, yco-=6, - menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Delete|X", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_CHANNELS_DELETE, ""); - - if(curarea->headertype==HEADERTOP) { - uiBlockSetDirection(block, UI_DOWN); - } - else { - uiBlockSetDirection(block, UI_TOP); - uiBlockFlipOrder(block); - } - - uiTextBoundsBlock(block, 50); - uiEndBlock(C, block); - - return block; -} - -/* Select menu --------------------------- */ - -static void do_selectmenu_columnmenu(bContext *C, void *arg, int event) -{ - switch (event) { - case ACTMENU_SEL_COLUMN_MARKERSBETWEEN: - //markers_selectkeys_between(); - break; - case ACTMENU_SEL_COLUMN_KEYS: - //column_select_action_keys(1); - break; - case ACTMENU_SEL_COLUMN_MARKERSCOLUMN: - //column_select_action_keys(2); - break; - case ACTMENU_SEL_COLUMN_CFRA: - //column_select_action_keys(3); - break; - } -} - -static uiBlock *action_selectmenu_columnmenu(bContext *C, ARegion *ar, void *arg_unused) -{ - SpaceAction *saction= (SpaceAction*)CTX_wm_space_data(C); - uiBlock *block; - short yco= 0, menuwidth=120; - - block= uiBeginBlock(C, ar, "action_selectmenu_columnmenu", UI_EMBOSSP); - uiBlockSetButmFunc(block, do_selectmenu_columnmenu, NULL); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "On Selected Keys|K", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_SEL_COLUMN_KEYS, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "On Current Frame|Ctrl K", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_SEL_COLUMN_CFRA, ""); - - if (SACTION_HASMARKERS) { - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "On Selected Markers|Shift K", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_SEL_COLUMN_MARKERSCOLUMN, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Between Selected Markers|Alt K", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_SEL_COLUMN_MARKERSBETWEEN, ""); - } - - uiBlockSetDirection(block, UI_RIGHT); - uiTextBoundsBlock(block, 60); - - return block; -} - -static void do_selectmenu(bContext *C, void *arg, int event) -{ - SpaceAction *saction= (SpaceAction*)CTX_wm_space_data(C); - //Key *key; - - if (saction == NULL) return; - - //key = get_action_mesh_key(); - - switch(event) - { - case ACTMENU_SEL_BORDER: /* Border Select */ - //borderselect_action(); - break; - - case ACTMENU_SEL_BORDERC: /* Border Select */ - //borderselect_actionchannels(); - break; - - case ACTMENU_SEL_BORDERM: /* Border Select */ - //borderselect_markers(); - break; - - case ACTMENU_SEL_ALL_KEYS: /* Select/Deselect All Keys */ - /*deselect_action_keys(1, 1); - BIF_undo_push("(De)Select Keys"); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWNLA, 0); - allqueue(REDRAWIPO, 0);*/ - break; - - case ACTMENU_SEL_ALL_CHAN: /* Select/Deselect All Channels */ - /*deselect_action_channels(1); - BIF_undo_push("(De)Select Action Channels"); - allqueue(REDRAWVIEW3D, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWNLA, 0); - allqueue(REDRAWIPO, 0);*/ - break; - - case ACTMENU_SEL_ALL_MARKERS: /* select/deselect all markers */ - /*deselect_markers(1, 0); - BIF_undo_push("(De)Select Markers"); - allqueue(REDRAWMARKER, 0);*/ - break; - - case ACTMENU_SEL_INVERSE_KEYS: /* invert selection status of keys */ - /*deselect_action_keys(0, 2); - BIF_undo_push("Inverse Keys"); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWNLA, 0); - allqueue(REDRAWIPO, 0);*/ - break; - - case ACTMENU_SEL_INVERSE_CHANNELS: /* invert selection status of channels */ - /*deselect_action_channels(2); - BIF_undo_push("Inverse Action Channels"); - allqueue(REDRAWVIEW3D, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWNLA, 0); - allqueue(REDRAWIPO, 0);*/ - break; - - case ACTMENU_SEL_INVERSE_MARKERS: /* invert selection of markers */ - /*deselect_markers(0, 2); - BIF_undo_push("Inverse Action Channels"); - allqueue(REDRAWMARKER, 0);*/ - break; - - case ACTMENU_SEL_LEFTKEYS: - //selectkeys_leftright(1, SELECT_REPLACE); - break; - - case ACTMENU_SEL_RIGHTKEYS: - //selectkeys_leftright(0, SELECT_REPLACE); - break; - } -} - -static uiBlock *action_selectmenu(bContext *C, ARegion *ar, void *arg_unused) -{ - ScrArea *curarea= CTX_wm_area(C); - SpaceAction *saction= (SpaceAction*)CTX_wm_space_data(C); - uiBlock *block; - short yco= 0, menuwidth=120; - - block= uiBeginBlock(C, ar, "action_selectmenu", UI_EMBOSSP); - uiBlockSetButmFunc(block, do_selectmenu, NULL); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Border Select Keys|B", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_SEL_BORDER, ""); - if (SACTION_HASMARKERS) { - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Border Select Markers|Ctrl B", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_SEL_BORDERM, ""); - } - if (saction->mode != SACTCONT_SHAPEKEY) { - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Border Select Channels|B", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_SEL_BORDERC, ""); - } - - uiDefBut(block, SEPR, 0, "", 0, yco-=6, - menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Select/Deselect All Keys|A", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_SEL_ALL_KEYS, ""); - if (SACTION_HASMARKERS) { - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Select/Deselect All Markers|Ctrl A", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_SEL_ALL_MARKERS, ""); - } - if (saction->mode != SACTCONT_SHAPEKEY) { - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Select/Deselect All Channels|A", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_SEL_ALL_CHAN, ""); - } - - uiDefBut(block, SEPR, 0, "", 0, yco-=6, - menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Inverse Keys|Ctrl I", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_SEL_INVERSE_KEYS, ""); - if (SACTION_HASMARKERS) { - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Inverse Markers|Ctrl Shift I", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_SEL_INVERSE_MARKERS, ""); - } - if (saction->mode != SACTCONT_SHAPEKEY) { - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Inverse All Channels|Ctrl I", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_SEL_INVERSE_CHANNELS, ""); - } - - uiDefBut(block, SEPR, 0, "", 0, yco-=6, - menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Back In Time|Alt RMB", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_SEL_LEFTKEYS, ""); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Ahead In Time|Alt RMB", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_SEL_RIGHTKEYS, ""); - - uiDefBut(block, SEPR, 0, "", 0, yco-=6, - menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - - uiDefIconTextBlockBut(block, action_selectmenu_columnmenu, - NULL, ICON_RIGHTARROW_THIN, "Column Select Keys", 0, yco-=20, 120, 20, ""); - - if(curarea->headertype==HEADERTOP) { - uiBlockSetDirection(block, UI_DOWN); - } - else { - uiBlockSetDirection(block, UI_TOP); - uiBlockFlipOrder(block); - } - - uiTextBoundsBlock(block, 50); - uiEndBlock(C, block); - - return block; -} - -/* View menu --------------------------- */ - -static void do_viewmenu(bContext *C, void *arg, int event) -{ - switch(event) { - case ACTMENU_VIEW_CENTERVIEW: /* Center View to Current Frame */ - //center_currframe(); - break; - case ACTMENU_VIEW_AUTOUPDATE: /* Update Automatically */ - /*if (BTST(G.saction->lock, 0)) - G.saction->lock = BCLR(G.saction->lock, 0); - else - G.saction->lock = BSET(G.saction->lock, 0);*/ - break; - case ACTMENU_VIEW_PLAY3D: /* Play Back Animation */ - //play_anim(0); - break; - case ACTMENU_VIEW_PLAYALL: /* Play Back Animation in All */ - //play_anim(1); - break; - case ACTMENU_VIEW_ALL: /* View All */ - //do_action_buttons(B_ACTHOME); - break; - case ACTMENU_VIEW_LOCK: - /*G.v2d->flag ^= V2D_VIEWLOCK; - if (G.v2d->flag & V2D_VIEWLOCK) - view2d_do_locks(curarea, 0);*/ - break; - case ACTMENU_VIEW_SLIDERS: /* Show sliders (when applicable) */ - //G.saction->flag ^= SACTION_SLIDERS; - break; - case ACTMENU_VIEW_MAXIMIZE: /* Maximize Window */ - /* using event B_FULL */ - break; - case ACTMENU_VIEW_NEXTMARKER: /* Jump to next marker */ - //nextprev_marker(1); - break; - case ACTMENU_VIEW_PREVMARKER: /* Jump to previous marker */ - //nextprev_marker(-1); - break; - case ACTMENU_VIEW_TIME: /* switch between frames and seconds display */ - //G.saction->flag ^= SACTION_DRAWTIME; - break; - case ACTMENU_VIEW_NOHIDE: /* Show hidden channels */ - //G.saction->flag ^= SACTION_NOHIDE; - break; - case ACTMENU_VIEW_NEXTKEYFRAME: /* Jump to next keyframe */ - //nextprev_action_keyframe(1); - break; - case ACTMENU_VIEW_PREVKEYFRAME: /* Jump to previous keyframe */ - //nextprev_action_keyframe(-1); - break; - case ACTMENU_VIEW_TRANSDELDUPS: /* Don't delete duplicate/overlapping keyframes after transform */ - //G.saction->flag ^= SACTION_NOTRANSKEYCULL; - break; - case ACTMENU_VIEW_HORIZOPTIMISE: /* Include keyframes not in view (horizontally) when preparing to draw */ - //G.saction->flag ^= SACTION_HORIZOPTIMISEON; - break; - case ACTMENU_VIEW_GCOLORS: /* Draw grouped-action channels using its group's color */ - //G.saction->flag ^= SACTION_NODRAWGCOLORS; - break; - case ACTMENU_VIEW_PREVRANGESET: /* Set preview range */ - //anim_previewrange_set(); - break; - case ACTMENU_VIEW_PREVRANGECLEAR: /* Clear preview range */ - //anim_previewrange_clear(); - break; - case ACTMENU_VIEW_PREVRANGEAUTO: /* Auto preview-range length */ - //action_previewrange_set(G.saction->action); - break; - } -} - -static uiBlock *action_viewmenu(bContext *C, ARegion *ar, void *arg_unused) -{ - ScrArea *curarea= CTX_wm_area(C); - SpaceAction *saction= (SpaceAction*)CTX_wm_space_data(C); - View2D *v2d= UI_view2d_fromcontext_rwin(C); - uiBlock *block; - short yco= 0, menuwidth=120; - - block= uiBeginBlock(C, ar, "viewmenu", UI_EMBOSSP); - uiBlockSetButmFunc(block, do_viewmenu, NULL); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Center View to Current Frame|C", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 1, - ACTMENU_VIEW_CENTERVIEW, ""); - - uiDefBut(block, SEPR, 0, "", 0, yco-=6, - menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - - if (saction->flag & SACTION_DRAWTIME) { - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Show Frames|Ctrl T", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 1, - ACTMENU_VIEW_TIME, ""); - } - else { - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Show Seconds|Ctrl T", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 1, - ACTMENU_VIEW_TIME, ""); - } - - uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - - if (saction->mode == SACTCONT_GPENCIL) { - // this option may get removed in future - uiDefIconTextBut(block, BUTM, 1, (saction->flag & SACTION_HORIZOPTIMISEON)?ICON_CHECKBOX_HLT:ICON_CHECKBOX_DEHLT, - "Cull Out-of-View Keys (Time)|", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 1, - ACTMENU_VIEW_HORIZOPTIMISE, ""); - } - else { - uiDefIconTextBut(block, BUTM, 1, (saction->flag & SACTION_SLIDERS)?ICON_CHECKBOX_HLT:ICON_CHECKBOX_DEHLT, - "Show Sliders|", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 1, - ACTMENU_VIEW_SLIDERS, ""); - - uiDefIconTextBut(block, BUTM, 1, (saction->flag & SACTION_NOHIDE)?ICON_CHECKBOX_HLT:ICON_CHECKBOX_DEHLT, - "Show Hidden Channels|", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 1, - ACTMENU_VIEW_NOHIDE, ""); - - uiDefIconTextBut(block, BUTM, 1, (saction->flag & SACTION_NODRAWGCOLORS)?ICON_CHECKBOX_DEHLT:ICON_CHECKBOX_HLT, - "Use Group Colors|", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 1, - ACTMENU_VIEW_GCOLORS, ""); - - // this option may get removed in future - uiDefIconTextBut(block, BUTM, 1, (saction->flag & SACTION_HORIZOPTIMISEON)?ICON_CHECKBOX_HLT:ICON_CHECKBOX_DEHLT, - "Cull Out-of-View Keys (Time)|", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 1, - ACTMENU_VIEW_HORIZOPTIMISE, ""); - - uiDefIconTextBut(block, BUTM, 1, (saction->flag & SACTION_NOTRANSKEYCULL)?ICON_CHECKBOX_DEHLT:ICON_CHECKBOX_HLT, - "AutoMerge Keyframes|", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 1, - ACTMENU_VIEW_TRANSDELDUPS, ""); - } - - - uiDefIconTextBut(block, BUTM, 1, (v2d->flag & V2D_VIEWSYNC_SCREEN_TIME)?ICON_CHECKBOX_HLT:ICON_CHECKBOX_DEHLT, - "Lock Time to Other Windows|", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 1, - ACTMENU_VIEW_LOCK, ""); - - /*uiDefIconTextBut(block, BUTM, 1, BTST(saction->lock, 0)?ICON_CHECKBOX_HLT:ICON_CHECKBOX_DEHLT, - "Update Automatically|", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 1, - ACTMENU_VIEW_AUTOUPDATE, "");*/ - - uiDefBut(block, SEPR, 0, "", 0, yco-=6, - menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Jump To Next Marker|PageUp", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_VIEW_NEXTMARKER, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Jump To Prev Marker|PageDown", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_VIEW_PREVMARKER, ""); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Jump To Next Keyframe|Ctrl PageUp", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_VIEW_NEXTKEYFRAME, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Jump To Prev Keyframe|Ctrl PageDown", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_VIEW_PREVKEYFRAME, ""); - - uiDefBut(block, SEPR, 0, "", 0, yco-=6, - menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Play Back Animation|Alt A", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 1, - ACTMENU_VIEW_PLAY3D, ""); - //uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - // "Play Back Animation in 3D View|Alt Shift A", 0, yco-=20, - // menuwidth, 19, NULL, 0.0, 0.0, 1, - // ACTMENU_VIEW_PLAYALL, ""); - - uiDefBut(block, SEPR, 0, "", 0, yco-=6, - menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Set Preview Range|Ctrl P", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 1, - ACTMENU_VIEW_PREVRANGESET, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Clear Preview Range|Alt P", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 1, - ACTMENU_VIEW_PREVRANGECLEAR, ""); - - if ((saction->mode == SACTCONT_ACTION) && (saction->action)) { - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Preview Range from Action Length|Ctrl Alt P", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 1, - ACTMENU_VIEW_PREVRANGEAUTO, ""); - } - - uiDefBut(block, SEPR, 0, "", 0, yco-=6, - menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "View All|Home", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 1, - ACTMENU_VIEW_ALL, ""); - -/* if (!curarea->full) - uiDefIconTextBut(block, BUTM, B_FULL, ICON_BLANK1, - "Maximize Window|Ctrl UpArrow", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_VIEW_MAXIMIZE, ""); + if (sa->full) + uiItemO(layout, NULL, 0, "SCREEN_OT_screen_full_area"); // "Tile Window", Ctrl UpArrow else - uiDefIconTextBut(block, BUTM, B_FULL, ICON_BLANK1, - "Tile Window|Ctrl DownArrow", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_VIEW_MAXIMIZE, ""); -*/ + uiItemO(layout, NULL, 0, "SCREEN_OT_screen_full_area"); // "Maximize Window", Ctrl DownArrow +} + +static void act_selectmenu(bContext *C, uiLayout *layout, void *arg_unused) +{ + uiItemO(layout, NULL, 0, "ACT_OT_select_all_toggle"); + uiItemBooleanO(layout, "Invert All", 0, "ACT_OT_select_all_toggle", "invert", 1); - if (curarea->headertype==HEADERTOP) { - uiBlockSetDirection(block, UI_DOWN); - } - else { - uiBlockSetDirection(block, UI_TOP); - uiBlockFlipOrder(block); - } + uiItemS(layout); - uiTextBoundsBlock(block, 50); - uiEndBlock(C, block); + uiItemO(layout, NULL, 0, "ACT_OT_select_border"); + uiItemBooleanO(layout, "Border Axis Range", 0, "ACT_OT_select_border", "axis_range", 1); - return block; + uiItemS(layout); + + uiItemEnumO(layout, "Columns on Selected Keys", 0, "ACT_OT_select_column", "mode", ACTKEYS_COLUMNSEL_KEYS); + uiItemEnumO(layout, "Column on Current Frame", 0, "ACT_OT_select_column", "mode", ACTKEYS_COLUMNSEL_CFRA); + + uiItemEnumO(layout, "Columns on Selected Markers", 0, "ACT_OT_select_column", "mode", ACTKEYS_COLUMNSEL_MARKERS_COLUMN); + uiItemEnumO(layout, "Between Selected Markers", 0, "ACT_OT_select_column", "mode", ACTKEYS_COLUMNSEL_MARKERS_BETWEEN); +} + +static void act_channelmenu(bContext *C, uiLayout *layout, void *arg_unused) +{ + uiItemO(layout, NULL, 0, "ANIM_OT_channels_setting_toggle"); + uiItemO(layout, NULL, 0, "ANIM_OT_channels_setting_enable"); + uiItemO(layout, NULL, 0, "ANIM_OT_channels_setting_disable"); + + uiItemS(layout); + + uiItemO(layout, NULL, 0, "ANIM_OT_channels_editable_toggle"); + + uiItemS(layout); + + uiItemO(layout, NULL, 0, "ANIM_OT_channels_expand"); + uiItemO(layout, NULL, 0, "ANIM_OT_channels_collapse"); +} + +static void act_gplayermenu(bContext *C, uiLayout *layout, void *arg_unused) +{ + //uiItemMenuF(layout, "Transform", 0, nla_edit_transformmenu); + //uiItemS(layout); + //uiItemO(layout, NULL, 0, "NLAEDIT_OT_duplicate"); +} + +static void act_edit_transformmenu(bContext *C, uiLayout *layout, void *arg_unused) +{ + uiItemEnumO(layout, "Grab/Move", 0, "TFM_OT_transform", "mode", TFM_TIME_TRANSLATE); + uiItemEnumO(layout, "Extend", 0, "TFM_OT_transform", "mode", TFM_TIME_EXTEND); + uiItemEnumO(layout, "Scale", 0, "TFM_OT_transform", "mode", TFM_TIME_SCALE); +} + +static void act_edit_snapmenu(bContext *C, uiLayout *layout, void *arg_unused) +{ + uiItemEnumO(layout, "To Current Frame", 0, "ACT_OT_snap", "mode", ACTKEYS_SNAP_CFRA); + uiItemEnumO(layout, "To Nearest Frame", 0, "ACT_OT_snap", "mode", ACTKEYS_SNAP_NEAREST_FRAME); + uiItemEnumO(layout, "To Nearest Second", 0, "ACT_OT_snap", "mode", ACTKEYS_SNAP_NEAREST_SECOND); + uiItemEnumO(layout, "To Nearest Marker", 0, "ACT_OT_snap", "mode", ACTKEYS_SNAP_NEAREST_MARKER); +} + +static void act_edit_mirrormenu(bContext *C, uiLayout *layout, void *arg_unused) +{ + uiItemEnumO(layout, "Over Current Frame", 0, "ACT_OT_mirror", "mode", ACTKEYS_MIRROR_CFRA); + uiItemEnumO(layout, "Over Vertical Axis", 0, "ACT_OT_mirror", "mode", ACTKEYS_MIRROR_YAXIS); + uiItemEnumO(layout, "Over Horizontal Axis", 0, "ACT_OT_mirror", "mode", ACTKEYS_MIRROR_XAXIS); + uiItemEnumO(layout, "Over Selected Marker", 0, "ACT_OT_mirror", "mode", ACTKEYS_MIRROR_MARKER); +} + +static void act_edit_handlesmenu(bContext *C, uiLayout *layout, void *arg_unused) +{ + uiItemEnumO(layout, NULL, 0, "ACT_OT_handle_type_set", "type", HD_FREE); + uiItemEnumO(layout, NULL, 0, "ACT_OT_handle_type_set", "type", HD_AUTO); + uiItemEnumO(layout, NULL, 0, "ACT_OT_handle_type_set", "type", HD_VECT); + uiItemEnumO(layout, NULL, 0, "ACT_OT_handle_type_set", "type", HD_ALIGN); + uiItemEnumO(layout, NULL, 0, "ACT_OT_handle_type_set", "type", HD_AUTO_ANIM); // xxx? +} + +static void act_edit_ipomenu(bContext *C, uiLayout *layout, void *arg_unused) +{ + uiItemEnumO(layout, NULL, 0, "ACT_OT_interpolation_type_set", "type", BEZT_IPO_CONST); + uiItemEnumO(layout, NULL, 0, "ACT_OT_interpolation_type_set", "type", BEZT_IPO_LIN); + uiItemEnumO(layout, NULL, 0, "ACT_OT_interpolation_type_set", "type", BEZT_IPO_BEZ); +} + +static void act_edit_expomenu(bContext *C, uiLayout *layout, void *arg_unused) +{ + uiItemEnumO(layout, NULL, 0, "ACT_OT_extrapolation_type_set", "type", FCURVE_EXTRAPOLATE_CONSTANT); + uiItemEnumO(layout, NULL, 0, "ACT_OT_extrapolation_type_set", "type", FCURVE_EXTRAPOLATE_LINEAR); +} + +static void act_editmenu(bContext *C, uiLayout *layout, void *arg_unused) +{ + uiItemMenuF(layout, "Transform", 0, act_edit_transformmenu); + uiItemMenuF(layout, "Snap", 0, act_edit_snapmenu); + uiItemMenuF(layout, "Mirror", 0, act_edit_mirrormenu); + + uiItemS(layout); + + uiItemO(layout, NULL, 0, "ACT_OT_insert"); + + uiItemS(layout); + + uiItemO(layout, NULL, 0, "ACT_OT_duplicate"); + uiItemO(layout, NULL, 0, "ACT_OT_delete"); + + uiItemS(layout); + + uiItemMenuF(layout, "Handle Type", 0, act_edit_handlesmenu); + uiItemMenuF(layout, "Interpolation Mode", 0, act_edit_ipomenu); + uiItemMenuF(layout, "Extrapolation Mode", 0, act_edit_expomenu); + + uiItemS(layout); + + uiItemO(layout, NULL, 0, "ACT_OT_clean"); + uiItemO(layout, NULL, 0, "ACT_OT_sample"); + + uiItemS(layout); + + uiItemO(layout, NULL, 0, "ACT_OT_copy"); + uiItemO(layout, NULL, 0, "ACT_OT_paste"); } /* ************************ header area region *********************** */ static void do_action_buttons(bContext *C, void *arg, int event) { - switch(event) { + switch (event) { case B_REDR: ED_area_tag_redraw(CTX_wm_area(C)); break; - - case B_ACTCOPYKEYS: - WM_operator_name_call(C, "ACT_OT_keyframes_copy", WM_OP_EXEC_REGION_WIN, NULL); - break; - case B_ACTPASTEKEYS: - WM_operator_name_call(C, "ACT_OT_keyframes_paste", WM_OP_EXEC_REGION_WIN, NULL); - break; } } @@ -1622,45 +314,38 @@ void action_header_buttons(const bContext *C, ARegion *ar) if ((sa->flag & HEADER_NO_PULLDOWN)==0) { xmax= GetButStringLength("View"); - uiDefPulldownBut(block, action_viewmenu, CTX_wm_area(C), - "View", xco, yco-2, xmax-3, 24, ""); + uiDefMenuBut(block, act_viewmenu, NULL, "View", xco, yco, xmax-3, 20, ""); xco+= xmax; xmax= GetButStringLength("Select"); - uiDefPulldownBut(block, action_selectmenu, CTX_wm_area(C), - "Select", xco, yco-2, xmax-3, 24, ""); + uiDefMenuBut(block, act_selectmenu, NULL, "Select", xco, yco, xmax-3, 20, ""); xco+= xmax; if ( (saction->mode == SACTCONT_DOPESHEET) || ((saction->action) && (saction->mode==SACTCONT_ACTION)) ) { xmax= GetButStringLength("Channel"); - uiDefPulldownBut(block, action_channelmenu, CTX_wm_area(C), - "Channel", xco, yco-2, xmax-3, 24, ""); + uiDefMenuBut(block, act_channelmenu, NULL, "Channel", xco, yco, xmax-3, 20, ""); xco+= xmax; } else if (saction->mode==SACTCONT_GPENCIL) { xmax= GetButStringLength("Channel"); - uiDefPulldownBut(block, action_gplayermenu, CTX_wm_area(C), - "Channel", xco, yco-2, xmax-3, 24, ""); + uiDefMenuBut(block, act_gplayermenu, NULL, "Channel", xco, yco, xmax-3, 20, ""); xco+= xmax; } - xmax= GetButStringLength("Marker"); - uiDefPulldownBut(block, action_markermenu, CTX_wm_area(C), - "Marker", xco, yco-2, xmax-3, 24, ""); - xco+= xmax; + //xmax= GetButStringLength("Marker"); + //uiDefMenuBut(block, act_markermenu, NULL, "Marker", xco, yco, xmax-3, 20, ""); + //xco+= xmax; if (saction->mode == SACTCONT_GPENCIL) { - xmax= GetButStringLength("Frame"); - uiDefPulldownBut(block, action_framemenu, CTX_wm_area(C), - "Frame", xco, yco-2, xmax-3, 24, ""); - xco+= xmax; + //xmax= GetButStringLength("Frame"); + //uiDefMenuBut(block, act_selectmenu, NULL, "Frame", xco, yco, xmax-3, 20, ""); + //xco+= xmax; } else { xmax= GetButStringLength("Key"); - uiDefPulldownBut(block, action_keymenu, CTX_wm_area(C), - "Key", xco, yco-2, xmax-3, 24, ""); + uiDefMenuBut(block, act_editmenu, NULL, "Key", xco, yco, xmax-3, 20, ""); xco+= xmax; } } @@ -1712,8 +397,8 @@ void action_header_buttons(const bContext *C, ARegion *ar) /* COPY PASTE */ uiBlockBeginAlign(block); - uiDefIconBut(block, BUT, B_ACTCOPYKEYS, ICON_COPYDOWN, xco,yco,XIC,YIC, 0, 0, 0, 0, 0, "Copies the selected keyframes from the selected channel(s) to the buffer"); - uiDefIconBut(block, BUT, B_ACTPASTEKEYS, ICON_PASTEDOWN, xco+=XIC,yco,XIC,YIC, 0, 0, 0, 0, 0, "Pastes the keyframes from the buffer"); + uiDefIconButO(block, BUT, "ACT_OT_copy", WM_OP_INVOKE_REGION_WIN, ICON_COPYDOWN, xco,yco,XIC,YIC, "Copies the selected keyframes to the buffer."); + uiDefIconButO(block, BUT, "ACT_OT_paste", WM_OP_INVOKE_REGION_WIN, ICON_COPYDOWN, xco,yco,XIC,YIC, "Pastes the keyframes from the buffer into the selected channels."); uiBlockEndAlign(block); xco += (XIC + 8); diff --git a/source/blender/editors/space_action/action_intern.h b/source/blender/editors/space_action/action_intern.h index b4d2528b3b4..377b25030e5 100644 --- a/source/blender/editors/space_action/action_intern.h +++ b/source/blender/editors/space_action/action_intern.h @@ -53,10 +53,10 @@ void action_header_buttons(const struct bContext *C, struct ARegion *ar); /* ***************************************** */ /* action_select.c */ -void ACT_OT_keyframes_select_all_toggle(struct wmOperatorType *ot); -void ACT_OT_keyframes_select_border(struct wmOperatorType *ot); -void ACT_OT_keyframes_select_column(struct wmOperatorType *ot); -void ACT_OT_keyframes_clickselect(struct wmOperatorType *ot); +void ACT_OT_select_all_toggle(struct wmOperatorType *ot); +void ACT_OT_select_border(struct wmOperatorType *ot); +void ACT_OT_select_column(struct wmOperatorType *ot); +void ACT_OT_clickselect(struct wmOperatorType *ot); /* defines for left-right select tool */ enum { @@ -80,22 +80,23 @@ enum { void ACT_OT_previewrange_set(struct wmOperatorType *ot); void ACT_OT_view_all(struct wmOperatorType *ot); -void ACT_OT_keyframes_copy(struct wmOperatorType *ot); -void ACT_OT_keyframes_paste(struct wmOperatorType *ot); +void ACT_OT_copy(struct wmOperatorType *ot); +void ACT_OT_paste(struct wmOperatorType *ot); -void ACT_OT_keyframes_insert(struct wmOperatorType *ot); -void ACT_OT_keyframes_duplicate(struct wmOperatorType *ot); -void ACT_OT_keyframes_delete(struct wmOperatorType *ot); -void ACT_OT_keyframes_clean(struct wmOperatorType *ot); -void ACT_OT_keyframes_sample(struct wmOperatorType *ot); +void ACT_OT_insert(struct wmOperatorType *ot); +void ACT_OT_duplicate(struct wmOperatorType *ot); +void ACT_OT_delete(struct wmOperatorType *ot); +void ACT_OT_clean(struct wmOperatorType *ot); +void ACT_OT_sample(struct wmOperatorType *ot); -void ACT_OT_keyframes_handle_type_set(struct wmOperatorType *ot); -void ACT_OT_keyframes_interpolation_type(struct wmOperatorType *ot); -void ACT_OT_keyframes_extrapolation_type_set(struct wmOperatorType *ot); +void ACT_OT_handle_type_set(struct wmOperatorType *ot); +void ACT_OT_interpolation_type_set(struct wmOperatorType *ot); +void ACT_OT_extrapolation_type_set(struct wmOperatorType *ot); -void ACT_OT_keyframes_cfrasnap(struct wmOperatorType *ot); -void ACT_OT_keyframes_snap(struct wmOperatorType *ot); -void ACT_OT_keyframes_mirror(struct wmOperatorType *ot); +void ACT_OT_frame_jump(struct wmOperatorType *ot); + +void ACT_OT_snap(struct wmOperatorType *ot); +void ACT_OT_mirror(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 49a0befdbe2..1a677e9191d 100644 --- a/source/blender/editors/space_action/action_ops.c +++ b/source/blender/editors/space_action/action_ops.c @@ -63,25 +63,25 @@ void action_operatortypes(void) { /* keyframes */ /* selection */ - WM_operatortype_append(ACT_OT_keyframes_clickselect); - WM_operatortype_append(ACT_OT_keyframes_select_all_toggle); - WM_operatortype_append(ACT_OT_keyframes_select_border); - WM_operatortype_append(ACT_OT_keyframes_select_column); + WM_operatortype_append(ACT_OT_clickselect); + WM_operatortype_append(ACT_OT_select_all_toggle); + WM_operatortype_append(ACT_OT_select_border); + WM_operatortype_append(ACT_OT_select_column); /* editing */ - WM_operatortype_append(ACT_OT_keyframes_snap); - WM_operatortype_append(ACT_OT_keyframes_mirror); - WM_operatortype_append(ACT_OT_keyframes_cfrasnap); - WM_operatortype_append(ACT_OT_keyframes_handle_type_set); - WM_operatortype_append(ACT_OT_keyframes_interpolation_type); - WM_operatortype_append(ACT_OT_keyframes_extrapolation_type_set); - WM_operatortype_append(ACT_OT_keyframes_sample); - WM_operatortype_append(ACT_OT_keyframes_clean); - WM_operatortype_append(ACT_OT_keyframes_delete); - WM_operatortype_append(ACT_OT_keyframes_duplicate); - WM_operatortype_append(ACT_OT_keyframes_insert); - WM_operatortype_append(ACT_OT_keyframes_copy); - WM_operatortype_append(ACT_OT_keyframes_paste); + WM_operatortype_append(ACT_OT_snap); + WM_operatortype_append(ACT_OT_mirror); + WM_operatortype_append(ACT_OT_frame_jump); + WM_operatortype_append(ACT_OT_handle_type_set); + WM_operatortype_append(ACT_OT_interpolation_type_set); + WM_operatortype_append(ACT_OT_extrapolation_type_set); + WM_operatortype_append(ACT_OT_sample); + WM_operatortype_append(ACT_OT_clean); + WM_operatortype_append(ACT_OT_delete); + WM_operatortype_append(ACT_OT_duplicate); + WM_operatortype_append(ACT_OT_insert); + WM_operatortype_append(ACT_OT_copy); + WM_operatortype_append(ACT_OT_paste); WM_operatortype_append(ACT_OT_previewrange_set); WM_operatortype_append(ACT_OT_view_all); @@ -95,57 +95,58 @@ static void action_keymap_keyframes (wmWindowManager *wm, ListBase *keymap) /* action_select.c - selection tools */ /* click-select */ - WM_keymap_add_item(keymap, "ACT_OT_keyframes_clickselect", SELECTMOUSE, KM_PRESS, 0, 0); - kmi= WM_keymap_add_item(keymap, "ACT_OT_keyframes_clickselect", SELECTMOUSE, KM_PRESS, KM_ALT, 0); + WM_keymap_add_item(keymap, "ACT_OT_clickselect", SELECTMOUSE, KM_PRESS, 0, 0); + kmi= WM_keymap_add_item(keymap, "ACT_OT_clickselect", SELECTMOUSE, KM_PRESS, KM_ALT, 0); RNA_boolean_set(kmi->ptr, "column", 1); - kmi= WM_keymap_add_item(keymap, "ACT_OT_keyframes_clickselect", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0); + kmi= WM_keymap_add_item(keymap, "ACT_OT_clickselect", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0); RNA_boolean_set(kmi->ptr, "extend", 1); - kmi= WM_keymap_add_item(keymap, "ACT_OT_keyframes_clickselect", SELECTMOUSE, KM_PRESS, KM_ALT|KM_SHIFT, 0); + kmi= WM_keymap_add_item(keymap, "ACT_OT_clickselect", SELECTMOUSE, KM_PRESS, KM_ALT|KM_SHIFT, 0); RNA_boolean_set(kmi->ptr, "extend", 1); RNA_boolean_set(kmi->ptr, "column", 1); - kmi= WM_keymap_add_item(keymap, "ACT_OT_keyframes_clickselect", SELECTMOUSE, KM_PRESS, KM_CTRL, 0); + kmi= WM_keymap_add_item(keymap, "ACT_OT_clickselect", SELECTMOUSE, KM_PRESS, KM_CTRL, 0); RNA_enum_set(kmi->ptr, "left_right", ACTKEYS_LRSEL_TEST); /* deselect all */ - WM_keymap_add_item(keymap, "ACT_OT_keyframes_select_all_toggle", AKEY, KM_PRESS, 0, 0); - RNA_boolean_set(WM_keymap_add_item(keymap, "ACT_OT_keyframes_select_all_toggle", IKEY, KM_PRESS, KM_CTRL, 0)->ptr, "invert", 1); + WM_keymap_add_item(keymap, "ACT_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0); + RNA_boolean_set(WM_keymap_add_item(keymap, "ACT_OT_select_all_toggle", IKEY, KM_PRESS, KM_CTRL, 0)->ptr, "invert", 1); /* borderselect */ - WM_keymap_add_item(keymap, "ACT_OT_keyframes_select_border", BKEY, KM_PRESS, 0, 0); - RNA_boolean_set(WM_keymap_add_item(keymap, "ACT_OT_keyframes_select_border", BKEY, KM_PRESS, KM_ALT, 0)->ptr, "axis_range", 1); + WM_keymap_add_item(keymap, "ACT_OT_select_border", BKEY, KM_PRESS, 0, 0); + RNA_boolean_set(WM_keymap_add_item(keymap, "ACT_OT_select_border", BKEY, KM_PRESS, KM_ALT, 0)->ptr, "axis_range", 1); /* column select */ - RNA_enum_set(WM_keymap_add_item(keymap, "ACT_OT_keyframes_select_column", KKEY, KM_PRESS, 0, 0)->ptr, "mode", ACTKEYS_COLUMNSEL_KEYS); - RNA_enum_set(WM_keymap_add_item(keymap, "ACT_OT_keyframes_select_column", KKEY, KM_PRESS, KM_CTRL, 0)->ptr, "mode", ACTKEYS_COLUMNSEL_CFRA); - RNA_enum_set(WM_keymap_add_item(keymap, "ACT_OT_keyframes_select_column", KKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "mode", ACTKEYS_COLUMNSEL_MARKERS_COLUMN); - RNA_enum_set(WM_keymap_add_item(keymap, "ACT_OT_keyframes_select_column", KKEY, KM_PRESS, KM_ALT, 0)->ptr, "mode", ACTKEYS_COLUMNSEL_MARKERS_BETWEEN); + RNA_enum_set(WM_keymap_add_item(keymap, "ACT_OT_select_column", KKEY, KM_PRESS, 0, 0)->ptr, "mode", ACTKEYS_COLUMNSEL_KEYS); + RNA_enum_set(WM_keymap_add_item(keymap, "ACT_OT_select_column", KKEY, KM_PRESS, KM_CTRL, 0)->ptr, "mode", ACTKEYS_COLUMNSEL_CFRA); + RNA_enum_set(WM_keymap_add_item(keymap, "ACT_OT_select_column", KKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "mode", ACTKEYS_COLUMNSEL_MARKERS_COLUMN); + RNA_enum_set(WM_keymap_add_item(keymap, "ACT_OT_select_column", KKEY, KM_PRESS, KM_ALT, 0)->ptr, "mode", ACTKEYS_COLUMNSEL_MARKERS_BETWEEN); /* action_edit.c */ /* snap - current frame to selected keys */ - WM_keymap_add_item(keymap, "ACT_OT_keyframes_cfrasnap", SKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0); + // TODO: maybe since this is called jump, we're better to have it on -J? + WM_keymap_add_item(keymap, "ACT_OT_frame_jump", SKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0); /* menu + single-step transform */ - WM_keymap_add_item(keymap, "ACT_OT_keyframes_snap", SKEY, KM_PRESS, KM_SHIFT, 0); - WM_keymap_add_item(keymap, "ACT_OT_keyframes_mirror", MKEY, KM_PRESS, KM_SHIFT, 0); + WM_keymap_add_item(keymap, "ACT_OT_snap", SKEY, KM_PRESS, KM_SHIFT, 0); + WM_keymap_add_item(keymap, "ACT_OT_mirror", MKEY, KM_PRESS, KM_SHIFT, 0); /* menu + set setting */ - WM_keymap_add_item(keymap, "ACT_OT_keyframes_handle_type_set", HKEY, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "ACT_OT_keyframes_interpolation_type", TKEY, KM_PRESS, KM_SHIFT, 0); - WM_keymap_add_item(keymap, "ACT_OT_keyframes_extrapolation_type_set", EKEY, KM_PRESS, KM_SHIFT, 0); + WM_keymap_add_item(keymap, "ACT_OT_handle_type_set", HKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "ACT_OT_interpolation_type_set", TKEY, KM_PRESS, KM_SHIFT, 0); + WM_keymap_add_item(keymap, "ACT_OT_extrapolation_type_set", EKEY, KM_PRESS, KM_SHIFT, 0); /* destructive */ - WM_keymap_add_item(keymap, "ACT_OT_keyframes_clean", OKEY, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "ACT_OT_keyframes_sample", OKEY, KM_PRESS, KM_SHIFT, 0); + WM_keymap_add_item(keymap, "ACT_OT_clean", OKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "ACT_OT_sample", OKEY, KM_PRESS, KM_SHIFT, 0); - WM_keymap_add_item(keymap, "ACT_OT_keyframes_delete", XKEY, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "ACT_OT_keyframes_delete", DELKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "ACT_OT_delete", XKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "ACT_OT_delete", DELKEY, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "ACT_OT_keyframes_duplicate", DKEY, KM_PRESS, KM_SHIFT, 0); - WM_keymap_add_item(keymap, "ACT_OT_keyframes_insert", IKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "ACT_OT_duplicate", DKEY, KM_PRESS, KM_SHIFT, 0); + WM_keymap_add_item(keymap, "ACT_OT_insert", IKEY, KM_PRESS, 0, 0); /* copy/paste */ - WM_keymap_add_item(keymap, "ACT_OT_keyframes_copy", CKEY, KM_PRESS, KM_CTRL, 0); - WM_keymap_add_item(keymap, "ACT_OT_keyframes_paste", VKEY, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "ACT_OT_copy", CKEY, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "ACT_OT_paste", VKEY, KM_PRESS, KM_CTRL, 0); /* auto-set range */ WM_keymap_add_item(keymap, "ACT_OT_previewrange_set", PKEY, KM_PRESS, KM_CTRL|KM_ALT, 0); diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c index f99a08bc26d..4cb39712f84 100644 --- a/source/blender/editors/space_action/action_select.c +++ b/source/blender/editors/space_action/action_select.c @@ -179,11 +179,11 @@ static int actkeys_deselectall_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void ACT_OT_keyframes_select_all_toggle (wmOperatorType *ot) +void ACT_OT_select_all_toggle (wmOperatorType *ot) { /* identifiers */ ot->name= "Select All"; - ot->idname= "ACT_OT_keyframes_select_all_toggle"; + ot->idname= "ACT_OT_select_all_toggle"; /* api callbacks */ ot->exec= actkeys_deselectall_exec; @@ -338,11 +338,11 @@ static int actkeys_borderselect_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void ACT_OT_keyframes_select_border(wmOperatorType *ot) +void ACT_OT_select_border(wmOperatorType *ot) { /* identifiers */ ot->name= "Border Select"; - ot->idname= "ACT_OT_keyframes_select_border"; + ot->idname= "ACT_OT_select_border"; /* api callbacks */ ot->invoke= WM_border_select_invoke; @@ -555,11 +555,11 @@ static int actkeys_columnselect_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void ACT_OT_keyframes_select_column (wmOperatorType *ot) +void ACT_OT_select_column (wmOperatorType *ot) { /* identifiers */ ot->name= "Select All"; - ot->idname= "ACT_OT_keyframes_select_column"; + ot->idname= "ACT_OT_select_column"; /* api callbacks */ ot->exec= actkeys_columnselect_exec; @@ -960,11 +960,11 @@ static int actkeys_clickselect_invoke(bContext *C, wmOperator *op, wmEvent *even return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH; } -void ACT_OT_keyframes_clickselect (wmOperatorType *ot) +void ACT_OT_clickselect (wmOperatorType *ot) { /* identifiers */ ot->name= "Mouse Select Keys"; - ot->idname= "ACT_OT_keyframes_clickselect"; + ot->idname= "ACT_OT_clickselect"; /* api callbacks - absolutely no exec() this yet... */ ot->invoke= actkeys_clickselect_invoke; diff --git a/source/blender/editors/space_nla/nla_header.c b/source/blender/editors/space_nla/nla_header.c index f8c6ba2131a..1971b062c2b 100644 --- a/source/blender/editors/space_nla/nla_header.c +++ b/source/blender/editors/space_nla/nla_header.c @@ -110,6 +110,11 @@ static void nla_viewmenu(bContext *C, uiLayout *layout, void *arg_unused) uiItemS(layout); + uiItemO(layout, NULL, 0, "ANIM_OT_previewrange_set"); + uiItemO(layout, NULL, 0, "ANIM_OT_previewrange_clear"); + + uiItemS(layout); + //uiItemO(layout, NULL, 0, "NLA_OT_view_all"); if (sa->full) diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index d4e952882ce..01abc5450aa 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -366,6 +366,8 @@ extern StructRNA RNA_SoundSequence; extern StructRNA RNA_Space; extern StructRNA RNA_Space3DView; extern StructRNA RNA_SpaceButtonsWindow; +extern StructRNA RNA_SpaceDopeSheetEditor; +extern StructRNA RNA_SpaceGraphEditor; extern StructRNA RNA_SpaceImageEditor; extern StructRNA RNA_SpaceNLA; extern StructRNA RNA_SpaceOutliner; diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 78c49a493f4..d4f7c5b0bd1 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -30,6 +30,7 @@ #include "rna_internal.h" +#include "DNA_action_types.h" #include "DNA_object_types.h" #include "DNA_space_types.h" #include "DNA_view3d_types.h" @@ -89,9 +90,8 @@ static StructRNA* rna_Space_refine(struct PointerRNA *ptr) switch(space->spacetype) { case SPACE_VIEW3D: return &RNA_Space3DView; - /*case SPACE_IPO: + case SPACE_IPO: return &RNA_SpaceGraphEditor; - */ case SPACE_OUTLINER: return &RNA_SpaceOutliner; case SPACE_BUTS: @@ -109,9 +109,9 @@ static StructRNA* rna_Space_refine(struct PointerRNA *ptr) //case SPACE_IMASEL: // return &RNA_SpaceImageBrowser; /*case SPACE_SOUND: - return &RNA_SpaceAudioWindow; + return &RNA_SpaceAudioWindow;*/ case SPACE_ACTION: - return &RNA_SpaceDopeSheetEditor;*/ + return &RNA_SpaceDopeSheetEditor; case SPACE_NLA: return &RNA_SpaceNLA; /*case SPACE_SCRIPT: @@ -868,6 +868,94 @@ static void rna_def_space_text(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Replace Text", "Text to replace selected text with using the replace tool."); } +static void rna_def_space_dopesheet(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + static EnumPropertyItem mode_items[] = { + {SACTCONT_DOPESHEET, "DOPESHEET", 0, "DopeSheet", ""}, + {SACTCONT_ACTION, "ACTION", 0, "Action Editor", ""}, + {SACTCONT_SHAPEKEY, "SHAPEKEY", 0, "ShapeKey Editor", ""}, // XXX to be depreceated? + {SACTCONT_GPENCIL, "GPENCIL", 0, "Grease Pencil", ""}, + {0, NULL, 0, NULL, NULL}}; + + + 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."); + + /* mode */ + prop= RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "mode"); + RNA_def_property_enum_items(prop, mode_items); + RNA_def_property_ui_text(prop, "Mode", "Editing context being displayed."); + + /* display */ + prop= RNA_def_property(srna, "show_seconds", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SACTION_DRAWTIME); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); // XXX for now, only set with operator + RNA_def_property_ui_text(prop, "Show Seconds", "Show timing in seconds not frames."); + + prop= RNA_def_property(srna, "show_cframe_indicator", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SACTION_NODRAWCFRANUM); + RNA_def_property_ui_text(prop, "Show Frame Number Indicator", "Show frame number beside the current frame indicator line."); + + prop= RNA_def_property(srna, "show_sliders", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SACTION_SLIDERS); + RNA_def_property_ui_text(prop, "Show Sliders", "Show sliders beside F-Curve channels."); + + /* editing */ + prop= RNA_def_property(srna, "automerge_keyframes", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SACTION_NOTRANSKEYCULL); + RNA_def_property_ui_text(prop, "AutoMerge Keyframes", "Show handles of Bezier control points."); + + // TODO... autosnap, dopesheet? +} + +static void rna_def_space_graph(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + static EnumPropertyItem mode_items[] = { + {SIPO_MODE_ANIMATION, "FCURVES", 0, "F-Curves", ""}, + {SIPO_MODE_DRIVERS, "DRIVERS", 0, "Drivers", ""}, + {0, NULL, 0, NULL, NULL}}; + + + srna= RNA_def_struct(brna, "SpaceGraphEditor", "Space"); + RNA_def_struct_sdna(srna, "SpaceIpo"); + RNA_def_struct_ui_text(srna, "Space Graph Editor", "Graph Editor space data."); + + /* mode */ + prop= RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "mode"); + RNA_def_property_enum_items(prop, mode_items); + RNA_def_property_ui_text(prop, "Mode", "Editing context being displayed."); + + /* display */ + prop= RNA_def_property(srna, "show_seconds", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SIPO_DRAWTIME); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); // XXX for now, only set with operator + RNA_def_property_ui_text(prop, "Show Seconds", "Show timing in seconds not frames."); + + prop= RNA_def_property(srna, "show_cframe_indicator", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SIPO_NODRAWCFRANUM); + RNA_def_property_ui_text(prop, "Show Frame Number Indicator", "Show frame number beside the current frame indicator line."); + + prop= RNA_def_property(srna, "show_handles", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SIPO_NOHANDLES); + RNA_def_property_ui_text(prop, "Show Handles", "Show handles of Bezier control points."); + + /* editing */ + prop= RNA_def_property(srna, "automerge_keyframes", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SIPO_NOTRANSKEYCULL); + RNA_def_property_ui_text(prop, "AutoMerge Keyframes", "Show handles of Bezier control points."); + + // TODO... autosnap, dopesheet? +} + static void rna_def_space_nla(BlenderRNA *brna) { StructRNA *srna; @@ -886,7 +974,9 @@ static void rna_def_space_nla(BlenderRNA *brna) prop= RNA_def_property(srna, "show_cframe_indicator", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SNLA_NODRAWCFRANUM); RNA_def_property_ui_text(prop, "Show Frame Number Indicator", "Show frame number beside the current frame indicator line."); - + + /* editing */ + // TODO... autosnap, dopesheet? } void RNA_def_space(BlenderRNA *brna) @@ -899,6 +989,8 @@ void RNA_def_space(BlenderRNA *brna) rna_def_background_image(brna); rna_def_space_3dview(brna); rna_def_space_buttons(brna); + rna_def_space_dopesheet(brna); + rna_def_space_graph(brna); rna_def_space_nla(brna); } From f1fb09a493b79e6320a651a035203dff98c3b580 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Mon, 22 Jun 2009 04:23:06 +0000 Subject: [PATCH 053/114] NLA SoC: Graph Editor Menus + Operator Name Cleanup As with the DopeSheet, the names of operators in the Graph Editor have been cleaned up, and operators have been added to menus as appropriate to show their availability. Tweaked a few DopeSheet operator names to be more in line with the Graph Editor equivalents, and vica versa. TODO: now, the operator poll callbacks here need checking... --- .../editors/space_action/action_edit.c | 12 +- .../editors/space_action/action_header.c | 20 +- .../editors/space_action/action_intern.h | 6 +- .../blender/editors/space_action/action_ops.c | 12 +- .../editors/space_graph/graph_buttons.c | 6 +- .../blender/editors/space_graph/graph_edit.c | 92 +++---- .../editors/space_graph/graph_header.c | 259 +++++++++++++----- .../editors/space_graph/graph_intern.h | 50 ++-- .../blender/editors/space_graph/graph_ops.c | 135 ++++----- .../editors/space_graph/graph_select.c | 16 +- 10 files changed, 361 insertions(+), 247 deletions(-) diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index b2f4751fa25..deaa6597bd2 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -853,11 +853,11 @@ static int actkeys_expo_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void ACT_OT_extrapolation_type_set (wmOperatorType *ot) +void ACT_OT_extrapolation_type (wmOperatorType *ot) { /* identifiers */ ot->name= "Set Keyframe Extrapolation"; - ot->idname= "ACT_OT_extrapolation_type_set"; + ot->idname= "ACT_OT_extrapolation_type"; /* api callbacks */ ot->invoke= WM_menu_invoke; @@ -923,11 +923,11 @@ static int actkeys_ipo_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void ACT_OT_interpolation_type_set (wmOperatorType *ot) +void ACT_OT_interpolation_type (wmOperatorType *ot) { /* identifiers */ ot->name= "Set Keyframe Interpolation"; - ot->idname= "ACT_OT_interpolation_type_set"; + ot->idname= "ACT_OT_interpolation_type"; /* api callbacks */ ot->invoke= WM_menu_invoke; @@ -1011,11 +1011,11 @@ static int actkeys_handletype_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void ACT_OT_handle_type_set (wmOperatorType *ot) +void ACT_OT_handle_type (wmOperatorType *ot) { /* identifiers */ ot->name= "Set Keyframe Handle Type"; - ot->idname= "ACT_OT_handle_type_set"; + ot->idname= "ACT_OT_handle_type"; /* api callbacks */ ot->invoke= WM_menu_invoke; diff --git a/source/blender/editors/space_action/action_header.c b/source/blender/editors/space_action/action_header.c index 1bc30b2ac42..a9ce145088d 100644 --- a/source/blender/editors/space_action/action_header.c +++ b/source/blender/editors/space_action/action_header.c @@ -183,24 +183,24 @@ static void act_edit_mirrormenu(bContext *C, uiLayout *layout, void *arg_unused) static void act_edit_handlesmenu(bContext *C, uiLayout *layout, void *arg_unused) { - uiItemEnumO(layout, NULL, 0, "ACT_OT_handle_type_set", "type", HD_FREE); - uiItemEnumO(layout, NULL, 0, "ACT_OT_handle_type_set", "type", HD_AUTO); - uiItemEnumO(layout, NULL, 0, "ACT_OT_handle_type_set", "type", HD_VECT); - uiItemEnumO(layout, NULL, 0, "ACT_OT_handle_type_set", "type", HD_ALIGN); - uiItemEnumO(layout, NULL, 0, "ACT_OT_handle_type_set", "type", HD_AUTO_ANIM); // xxx? + uiItemEnumO(layout, NULL, 0, "ACT_OT_handle_type", "type", HD_FREE); + uiItemEnumO(layout, NULL, 0, "ACT_OT_handle_type", "type", HD_AUTO); + uiItemEnumO(layout, NULL, 0, "ACT_OT_handle_type", "type", HD_VECT); + uiItemEnumO(layout, NULL, 0, "ACT_OT_handle_type", "type", HD_ALIGN); + uiItemEnumO(layout, NULL, 0, "ACT_OT_handle_type", "type", HD_AUTO_ANIM); // xxx? } static void act_edit_ipomenu(bContext *C, uiLayout *layout, void *arg_unused) { - uiItemEnumO(layout, NULL, 0, "ACT_OT_interpolation_type_set", "type", BEZT_IPO_CONST); - uiItemEnumO(layout, NULL, 0, "ACT_OT_interpolation_type_set", "type", BEZT_IPO_LIN); - uiItemEnumO(layout, NULL, 0, "ACT_OT_interpolation_type_set", "type", BEZT_IPO_BEZ); + uiItemEnumO(layout, NULL, 0, "ACT_OT_interpolation_type", "type", BEZT_IPO_CONST); + uiItemEnumO(layout, NULL, 0, "ACT_OT_interpolation_type", "type", BEZT_IPO_LIN); + uiItemEnumO(layout, NULL, 0, "ACT_OT_interpolation_type", "type", BEZT_IPO_BEZ); } static void act_edit_expomenu(bContext *C, uiLayout *layout, void *arg_unused) { - uiItemEnumO(layout, NULL, 0, "ACT_OT_extrapolation_type_set", "type", FCURVE_EXTRAPOLATE_CONSTANT); - uiItemEnumO(layout, NULL, 0, "ACT_OT_extrapolation_type_set", "type", FCURVE_EXTRAPOLATE_LINEAR); + uiItemEnumO(layout, NULL, 0, "ACT_OT_extrapolation_type", "type", FCURVE_EXTRAPOLATE_CONSTANT); + uiItemEnumO(layout, NULL, 0, "ACT_OT_extrapolation_type", "type", FCURVE_EXTRAPOLATE_LINEAR); } static void act_editmenu(bContext *C, uiLayout *layout, void *arg_unused) diff --git a/source/blender/editors/space_action/action_intern.h b/source/blender/editors/space_action/action_intern.h index 377b25030e5..6ccdc07421b 100644 --- a/source/blender/editors/space_action/action_intern.h +++ b/source/blender/editors/space_action/action_intern.h @@ -89,9 +89,9 @@ void ACT_OT_delete(struct wmOperatorType *ot); void ACT_OT_clean(struct wmOperatorType *ot); void ACT_OT_sample(struct wmOperatorType *ot); -void ACT_OT_handle_type_set(struct wmOperatorType *ot); -void ACT_OT_interpolation_type_set(struct wmOperatorType *ot); -void ACT_OT_extrapolation_type_set(struct wmOperatorType *ot); +void ACT_OT_handle_type(struct wmOperatorType *ot); +void ACT_OT_interpolation_type(struct wmOperatorType *ot); +void ACT_OT_extrapolation_type(struct wmOperatorType *ot); void ACT_OT_frame_jump(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_action/action_ops.c b/source/blender/editors/space_action/action_ops.c index 1a677e9191d..c023062453c 100644 --- a/source/blender/editors/space_action/action_ops.c +++ b/source/blender/editors/space_action/action_ops.c @@ -72,9 +72,9 @@ void action_operatortypes(void) WM_operatortype_append(ACT_OT_snap); WM_operatortype_append(ACT_OT_mirror); WM_operatortype_append(ACT_OT_frame_jump); - WM_operatortype_append(ACT_OT_handle_type_set); - WM_operatortype_append(ACT_OT_interpolation_type_set); - WM_operatortype_append(ACT_OT_extrapolation_type_set); + WM_operatortype_append(ACT_OT_handle_type); + WM_operatortype_append(ACT_OT_interpolation_type); + WM_operatortype_append(ACT_OT_extrapolation_type); WM_operatortype_append(ACT_OT_sample); WM_operatortype_append(ACT_OT_clean); WM_operatortype_append(ACT_OT_delete); @@ -130,9 +130,9 @@ static void action_keymap_keyframes (wmWindowManager *wm, ListBase *keymap) WM_keymap_add_item(keymap, "ACT_OT_mirror", MKEY, KM_PRESS, KM_SHIFT, 0); /* menu + set setting */ - WM_keymap_add_item(keymap, "ACT_OT_handle_type_set", HKEY, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "ACT_OT_interpolation_type_set", TKEY, KM_PRESS, KM_SHIFT, 0); - WM_keymap_add_item(keymap, "ACT_OT_extrapolation_type_set", EKEY, KM_PRESS, KM_SHIFT, 0); + WM_keymap_add_item(keymap, "ACT_OT_handle_type", HKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "ACT_OT_interpolation_type", TKEY, KM_PRESS, KM_SHIFT, 0); + WM_keymap_add_item(keymap, "ACT_OT_extrapolation_type", EKEY, KM_PRESS, KM_SHIFT, 0); /* destructive */ WM_keymap_add_item(keymap, "ACT_OT_clean", OKEY, KM_PRESS, 0, 0); diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c index 5b00205b5d0..ea4f017c9bb 100644 --- a/source/blender/editors/space_graph/graph_buttons.c +++ b/source/blender/editors/space_graph/graph_buttons.c @@ -989,7 +989,7 @@ static void graph_panel_modifiers(const bContext *C, Panel *pa) /* 'add modifier' button at top of panel */ // XXX for now, this will be a operator button which calls a temporary 'add modifier' operator - uiDefButO(block, BUT, "GRAPHEDIT_OT_fmodifier_add", WM_OP_INVOKE_REGION_WIN, "Add Modifier", 10, 225, 150, 20, "Adds a new F-Curve Modifier for the active F-Curve"); + uiDefButO(block, BUT, "GRAPH_OT_fmodifier_add", WM_OP_INVOKE_REGION_WIN, "Add Modifier", 10, 225, 150, 20, "Adds a new F-Curve Modifier for the active F-Curve"); /* draw each modifier */ for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next) @@ -1069,10 +1069,10 @@ static int graph_properties(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void GRAPHEDIT_OT_properties(wmOperatorType *ot) +void GRAPH_OT_properties(wmOperatorType *ot) { ot->name= "Properties"; - ot->idname= "GRAPHEDIT_OT_properties"; + ot->idname= "GRAPH_OT_properties"; ot->exec= graph_properties; ot->poll= ED_operator_ipo_active; // xxx diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index 49397ed0edd..8903d95b288 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -180,11 +180,11 @@ static int graphkeys_previewrange_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void GRAPHEDIT_OT_previewrange_set (wmOperatorType *ot) +void GRAPH_OT_previewrange_set (wmOperatorType *ot) { /* identifiers */ ot->name= "Auto-Set Preview Range"; - ot->idname= "GRAPHEDIT_OT_previewrange_set"; + ot->idname= "GRAPH_OT_previewrange_set"; /* api callbacks */ ot->exec= graphkeys_previewrange_exec; @@ -227,11 +227,11 @@ static int graphkeys_viewall_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void GRAPHEDIT_OT_view_all (wmOperatorType *ot) +void GRAPH_OT_view_all (wmOperatorType *ot) { /* identifiers */ ot->name= "View All"; - ot->idname= "GRAPHEDIT_OT_view_all"; + ot->idname= "GRAPH_OT_view_all"; /* api callbacks */ ot->exec= graphkeys_viewall_exec; @@ -334,11 +334,11 @@ static int graphkeys_create_ghostcurves_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void GRAPHEDIT_OT_ghost_curves_create (wmOperatorType *ot) +void GRAPH_OT_ghost_curves_create (wmOperatorType *ot) { /* identifiers */ ot->name= "Create Ghost Curves"; - ot->idname= "GRAPHEDIT_OT_ghost_curves_create"; + ot->idname= "GRAPH_OT_ghost_curves_create"; ot->description= "Create snapshot (Ghosts) of selected F-Curves as background aid for active Graph Editor."; /* api callbacks */ @@ -377,11 +377,11 @@ static int graphkeys_clear_ghostcurves_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void GRAPHEDIT_OT_ghost_curves_clear (wmOperatorType *ot) +void GRAPH_OT_ghost_curves_clear (wmOperatorType *ot) { /* identifiers */ ot->name= "Create Ghost Curves"; - ot->idname= "GRAPHEDIT_OT_ghost_curves_clear"; + ot->idname= "GRAPH_OT_ghost_curves_clear"; ot->description= "Clear F-Curve snapshots (Ghosts) for active Graph Editor."; /* api callbacks */ @@ -461,11 +461,11 @@ static int graphkeys_click_insert_invoke (bContext *C, wmOperator *op, wmEvent * return graphkeys_click_insert_exec(C, op); } -void GRAPHEDIT_OT_keyframes_click_insert (wmOperatorType *ot) +void GRAPH_OT_click_insert (wmOperatorType *ot) { /* identifiers */ ot->name= "Click-Insert Keyframes"; - ot->idname= "GRAPHEDIT_OT_keyframes_click_insert"; + ot->idname= "GRAPH_OT_click_insert"; /* api callbacks */ ot->invoke= graphkeys_click_insert_invoke; @@ -544,11 +544,11 @@ static int graphkeys_copy_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void GRAPHEDIT_OT_keyframes_copy (wmOperatorType *ot) +void GRAPH_OT_copy (wmOperatorType *ot) { /* identifiers */ ot->name= "Copy Keyframes"; - ot->idname= "GRAPHEDIT_OT_keyframes_copy"; + ot->idname= "GRAPH_OT_copy"; /* api callbacks */ ot->exec= graphkeys_copy_exec; @@ -583,11 +583,11 @@ static int graphkeys_paste_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void GRAPHEDIT_OT_keyframes_paste (wmOperatorType *ot) +void GRAPH_OT_paste (wmOperatorType *ot) { /* identifiers */ ot->name= "Paste Keyframes"; - ot->idname= "GRAPHEDIT_OT_keyframes_paste"; + ot->idname= "GRAPH_OT_paste"; /* api callbacks */ ot->exec= graphkeys_paste_exec; @@ -650,11 +650,11 @@ static int graphkeys_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *even return OPERATOR_FINISHED; } -void GRAPHEDIT_OT_keyframes_duplicate (wmOperatorType *ot) +void GRAPH_OT_duplicate (wmOperatorType *ot) { /* identifiers */ ot->name= "Duplicate Keyframes"; - ot->idname= "GRAPHEDIT_OT_keyframes_duplicate"; + ot->idname= "GRAPH_OT_duplicate"; /* api callbacks */ ot->invoke= graphkeys_duplicate_invoke; @@ -711,11 +711,11 @@ static int graphkeys_delete_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void GRAPHEDIT_OT_keyframes_delete (wmOperatorType *ot) +void GRAPH_OT_delete (wmOperatorType *ot) { /* identifiers */ ot->name= "Delete Keyframes"; - ot->idname= "GRAPHEDIT_OT_keyframes_delete"; + ot->idname= "GRAPH_OT_delete"; /* api callbacks */ ot->invoke= WM_operator_confirm; @@ -772,11 +772,11 @@ static int graphkeys_clean_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void GRAPHEDIT_OT_keyframes_clean (wmOperatorType *ot) +void GRAPH_OT_clean (wmOperatorType *ot) { /* identifiers */ ot->name= "Clean Keyframes"; - ot->idname= "GRAPHEDIT_OT_keyframes_clean"; + ot->idname= "GRAPH_OT_clean"; /* api callbacks */ //ot->invoke= // XXX we need that number popup for this! @@ -853,11 +853,11 @@ static int graphkeys_bake_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void GRAPHEDIT_OT_keyframes_bake (wmOperatorType *ot) +void GRAPH_OT_bake (wmOperatorType *ot) { /* identifiers */ ot->name= "Bake Curve"; - ot->idname= "GRAPHEDIT_OT_keyframes_bake"; + ot->idname= "GRAPH_OT_bake"; /* api callbacks */ ot->invoke= WM_operator_confirm; // FIXME... @@ -979,11 +979,11 @@ static int graphkeys_sample_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void GRAPHEDIT_OT_keyframes_sample (wmOperatorType *ot) +void GRAPH_OT_sample (wmOperatorType *ot) { /* identifiers */ ot->name= "Sample Keyframes"; - ot->idname= "GRAPHEDIT_OT_keyframes_sample"; + ot->idname= "GRAPH_OT_sample"; /* api callbacks */ ot->exec= graphkeys_sample_exec; @@ -1053,11 +1053,11 @@ static int graphkeys_expo_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void GRAPHEDIT_OT_keyframes_extrapolation_type (wmOperatorType *ot) +void GRAPH_OT_extrapolation_type (wmOperatorType *ot) { /* identifiers */ ot->name= "Set Keyframe Extrapolation"; - ot->idname= "GRAPHEDIT_OT_keyframes_extrapolation_type"; + ot->idname= "GRAPH_OT_extrapolation_type"; /* api callbacks */ ot->invoke= WM_menu_invoke; @@ -1121,11 +1121,11 @@ static int graphkeys_ipo_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void GRAPHEDIT_OT_keyframes_interpolation_type (wmOperatorType *ot) +void GRAPH_OT_interpolation_type (wmOperatorType *ot) { /* identifiers */ ot->name= "Set Keyframe Interpolation"; - ot->idname= "GRAPHEDIT_OT_keyframes_interpolation_type"; + ot->idname= "GRAPH_OT_interpolation_type"; /* api callbacks */ ot->invoke= WM_menu_invoke; @@ -1208,11 +1208,11 @@ static int graphkeys_handletype_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void GRAPHEDIT_OT_keyframes_handletype (wmOperatorType *ot) +void GRAPH_OT_handletype (wmOperatorType *ot) { /* identifiers */ ot->name= "Set Keyframe Handle Type"; - ot->idname= "GRAPHEDIT_OT_keyframes_handletype"; + ot->idname= "GRAPH_OT_handletype"; /* api callbacks */ ot->invoke= WM_menu_invoke; @@ -1298,11 +1298,11 @@ static int graphkeys_euler_filter_exec (bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } -void GRAPHEDIT_OT_keyframes_euler_filter (wmOperatorType *ot) +void GRAPH_OT_euler_filter (wmOperatorType *ot) { /* identifiers */ ot->name= "Euler Filter"; - ot->idname= "GRAPHEDIT_OT_keyframes_euler_filter"; + ot->idname= "GRAPH_OT_euler_filter"; /* api callbacks */ ot->exec= graphkeys_euler_filter_exec; @@ -1314,10 +1314,10 @@ void GRAPHEDIT_OT_keyframes_euler_filter (wmOperatorType *ot) #endif // XXX this is not ready for the primetime yet -/* ***************** Snap Current Frame Operator *********************** */ +/* ***************** Jump to Selected Frames Operator *********************** */ /* snap current-frame indicator to 'average time' of selected keyframe */ -static int graphkeys_cfrasnap_exec(bContext *C, wmOperator *op) +static int graphkeys_framejump_exec(bContext *C, wmOperator *op) { bAnimContext ac; ListBase anim_data= {NULL, NULL}; @@ -1353,14 +1353,14 @@ static int graphkeys_cfrasnap_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void GRAPHEDIT_OT_keyframes_cfrasnap (wmOperatorType *ot) +void GRAPH_OT_frame_jump (wmOperatorType *ot) { /* identifiers */ - ot->name= "Snap Current Frame to Keys"; - ot->idname= "GRAPHEDIT_OT_keyframes_cfrasnap"; + ot->name= "Jump to Frame"; + ot->idname= "GRAPH_OT_frame_jump"; /* api callbacks */ - ot->exec= graphkeys_cfrasnap_exec; + ot->exec= graphkeys_framejump_exec; ot->poll= ED_operator_areaactive; /* flags */ @@ -1444,11 +1444,11 @@ static int graphkeys_snap_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void GRAPHEDIT_OT_keyframes_snap (wmOperatorType *ot) +void GRAPH_OT_snap (wmOperatorType *ot) { /* identifiers */ ot->name= "Snap Keys"; - ot->idname= "GRAPHEDIT_OT_keyframes_snap"; + ot->idname= "GRAPH_OT_snap"; /* api callbacks */ ot->invoke= WM_menu_invoke; @@ -1555,11 +1555,11 @@ static int graphkeys_mirror_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void GRAPHEDIT_OT_keyframes_mirror (wmOperatorType *ot) +void GRAPH_OT_mirror (wmOperatorType *ot) { /* identifiers */ ot->name= "Mirror Keys"; - ot->idname= "GRAPHEDIT_OT_keyframes_mirror"; + ot->idname= "GRAPH_OT_mirror"; /* api callbacks */ ot->invoke= WM_menu_invoke; @@ -1609,11 +1609,11 @@ static int graphkeys_smooth_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void GRAPHEDIT_OT_keyframes_smooth (wmOperatorType *ot) +void GRAPH_OT_smooth (wmOperatorType *ot) { /* identifiers */ ot->name= "Smooth Keys"; - ot->idname= "GRAPHEDIT_OT_keyframes_smooth"; + ot->idname= "GRAPH_OT_smooth"; /* api callbacks */ ot->exec= graphkeys_smooth_exec; @@ -1671,11 +1671,11 @@ static int graph_fmodifier_add_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void GRAPHEDIT_OT_fmodifier_add (wmOperatorType *ot) +void GRAPH_OT_fmodifier_add (wmOperatorType *ot) { /* identifiers */ ot->name= "Add F-Curve Modifier"; - ot->idname= "GRAPHEDIT_OT_fmodifier_add"; + ot->idname= "GRAPH_OT_fmodifier_add"; /* api callbacks */ ot->invoke= WM_menu_invoke; diff --git a/source/blender/editors/space_graph/graph_header.c b/source/blender/editors/space_graph/graph_header.c index 178b4b4562f..0bd08625d68 100644 --- a/source/blender/editors/space_graph/graph_header.c +++ b/source/blender/editors/space_graph/graph_header.c @@ -47,11 +47,14 @@ #include "ED_types.h" #include "ED_util.h" +#include "RNA_access.h" + #include "WM_api.h" #include "WM_types.h" #include "BIF_gl.h" #include "BIF_glutil.h" +#include "BIF_transform.h" #include "UI_interface.h" #include "UI_resources.h" @@ -62,76 +65,173 @@ /* ********************************************************* */ /* Menu Defines... */ -/* button events */ +static void graph_viewmenu(bContext *C, uiLayout *layout, void *arg_unused) +{ + bScreen *sc= CTX_wm_screen(C); + ScrArea *sa= CTX_wm_area(C); + SpaceIpo *sipo= (SpaceIpo*)CTX_wm_space_data(C); + PointerRNA spaceptr; + + /* retrieve state */ + RNA_pointer_create(&sc->id, &RNA_SpaceGraphEditor, sipo, &spaceptr); + + /* create menu */ + uiItemO(layout, NULL, ICON_MENU_PANEL, "GRAPH_OT_properties"); + + uiItemS(layout); + + uiItemR(layout, NULL, 0, &spaceptr, "show_cframe_indicator", 0, 0, 0); + + if (sipo->flag & SIPO_NOHANDLES) + uiItemO(layout, "Show Handles", ICON_CHECKBOX_DEHLT, "GRAPH_OT_handles_view_toggle"); + else + uiItemO(layout, "Show Handles", ICON_CHECKBOX_HLT, "GRAPH_OT_handles_view_toggle"); + + uiItemR(layout, NULL, 0, &spaceptr, "automerge_keyframes", 0, 0, 0); + + if (sipo->flag & SIPO_DRAWTIME) + uiItemO(layout, "Show Frames", 0, "ANIM_OT_time_toggle"); + else + uiItemO(layout, "Show Seconds", 0, "ANIM_OT_time_toggle"); + + uiItemS(layout); + + uiItemO(layout, NULL, 0, "ANIM_OT_previewrange_set"); + uiItemO(layout, NULL, 0, "ANIM_OT_previewrange_clear"); + + uiItemO(layout, NULL, 0, "GRAPH_OT_previewrange_set"); + + uiItemS(layout); + + uiItemO(layout, NULL, 0, "GRAPH_OT_frame_jump"); + + uiItemO(layout, NULL, 0, "GRAPH_OT_view_all"); + + if (sa->full) + uiItemO(layout, NULL, 0, "SCREEN_OT_screen_full_area"); // "Tile Window", Ctrl UpArrow + else + uiItemO(layout, NULL, 0, "SCREEN_OT_screen_full_area"); // "Maximize Window", Ctrl DownArrow +} + +static void graph_selectmenu(bContext *C, uiLayout *layout, void *arg_unused) +{ + uiItemO(layout, NULL, 0, "GRAPH_OT_select_all_toggle"); + uiItemBooleanO(layout, "Invert All", 0, "GRAPH_OT_select_all_toggle", "invert", 1); + + uiItemS(layout); + + uiItemO(layout, NULL, 0, "GRAPH_OT_select_border"); + uiItemBooleanO(layout, "Border Axis Range", 0, "GRAPH_OT_select_border", "axis_range", 1); + + uiItemS(layout); + + uiItemEnumO(layout, "Columns on Selected Keys", 0, "GRAPH_OT_select_column", "mode", GRAPHKEYS_COLUMNSEL_KEYS); + uiItemEnumO(layout, "Column on Current Frame", 0, "GRAPH_OT_select_column", "mode", GRAPHKEYS_COLUMNSEL_CFRA); + + uiItemEnumO(layout, "Columns on Selected Markers", 0, "GRAPH_OT_select_column", "mode", GRAPHKEYS_COLUMNSEL_MARKERS_COLUMN); + uiItemEnumO(layout, "Between Selected Markers", 0, "GRAPH_OT_select_column", "mode", GRAPHKEYS_COLUMNSEL_MARKERS_BETWEEN); +} + +static void graph_channelmenu(bContext *C, uiLayout *layout, void *arg_unused) +{ + uiItemO(layout, NULL, 0, "ANIM_OT_channels_setting_toggle"); + uiItemO(layout, NULL, 0, "ANIM_OT_channels_setting_enable"); + uiItemO(layout, NULL, 0, "ANIM_OT_channels_setting_disable"); + + uiItemS(layout); + + uiItemO(layout, NULL, 0, "ANIM_OT_channels_editable_toggle"); + + uiItemS(layout); + + uiItemO(layout, NULL, 0, "ANIM_OT_channels_expand"); + uiItemO(layout, NULL, 0, "ANIM_OT_channels_collapse"); +} + +static void graph_edit_transformmenu(bContext *C, uiLayout *layout, void *arg_unused) +{ + uiItemEnumO(layout, "Grab/Move", 0, "TFM_OT_transform", "mode", TFM_TIME_TRANSLATE); + uiItemEnumO(layout, "Extend", 0, "TFM_OT_transform", "mode", TFM_TIME_EXTEND); + uiItemEnumO(layout, "Scale", 0, "TFM_OT_transform", "mode", TFM_TIME_SCALE); +} + +static void graph_edit_snapmenu(bContext *C, uiLayout *layout, void *arg_unused) +{ + uiItemEnumO(layout, "To Current Frame", 0, "GRAPH_OT_snap", "mode", GRAPHKEYS_SNAP_CFRA); + uiItemEnumO(layout, "To Nearest Frame", 0, "GRAPH_OT_snap", "mode", GRAPHKEYS_SNAP_NEAREST_FRAME); + uiItemEnumO(layout, "To Nearest Second", 0, "GRAPH_OT_snap", "mode", GRAPHKEYS_SNAP_NEAREST_SECOND); + uiItemEnumO(layout, "To Nearest Marker", 0, "GRAPH_OT_snap", "mode", GRAPHKEYS_SNAP_NEAREST_MARKER); +} + +static void graph_edit_mirrormenu(bContext *C, uiLayout *layout, void *arg_unused) +{ + uiItemEnumO(layout, "Over Current Frame", 0, "GRAPH_OT_mirror", "mode", GRAPHKEYS_MIRROR_CFRA); + uiItemEnumO(layout, "Over Vertical Axis", 0, "GRAPH_OT_mirror", "mode", GRAPHKEYS_MIRROR_YAXIS); + uiItemEnumO(layout, "Over Horizontal Axis", 0, "GRAPH_OT_mirror", "mode", GRAPHKEYS_MIRROR_XAXIS); + uiItemEnumO(layout, "Over Selected Marker", 0, "GRAPH_OT_mirror", "mode", GRAPHKEYS_MIRROR_MARKER); +} + +static void graph_edit_handlesmenu(bContext *C, uiLayout *layout, void *arg_unused) +{ + uiItemEnumO(layout, NULL, 0, "GRAPH_OT_handle_type", "type", HD_FREE); + uiItemEnumO(layout, NULL, 0, "GRAPH_OT_handle_type", "type", HD_AUTO); + uiItemEnumO(layout, NULL, 0, "GRAPH_OT_handle_type", "type", HD_VECT); + uiItemEnumO(layout, NULL, 0, "GRAPH_OT_handle_type", "type", HD_ALIGN); + uiItemEnumO(layout, NULL, 0, "GRAPH_OT_handle_type", "type", HD_AUTO_ANIM); // xxx? +} + +static void graph_edit_ipomenu(bContext *C, uiLayout *layout, void *arg_unused) +{ + uiItemEnumO(layout, NULL, 0, "GRAPH_OT_interpolation_type", "type", BEZT_IPO_CONST); + uiItemEnumO(layout, NULL, 0, "GRAPH_OT_interpolation_type", "type", BEZT_IPO_LIN); + uiItemEnumO(layout, NULL, 0, "GRAPH_OT_interpolation_type", "type", BEZT_IPO_BEZ); +} + +static void graph_edit_expomenu(bContext *C, uiLayout *layout, void *arg_unused) +{ + uiItemEnumO(layout, NULL, 0, "GRAPH_OT_extrapolation_type", "type", FCURVE_EXTRAPOLATE_CONSTANT); + uiItemEnumO(layout, NULL, 0, "GRAPH_OT_extrapolation_type", "type", FCURVE_EXTRAPOLATE_LINEAR); +} + +static void graph_editmenu(bContext *C, uiLayout *layout, void *arg_unused) +{ + uiItemMenuF(layout, "Transform", 0, graph_edit_transformmenu); + uiItemMenuF(layout, "Snap", 0, graph_edit_snapmenu); + uiItemMenuF(layout, "Mirror", 0, graph_edit_mirrormenu); + + uiItemS(layout); + + //uiItemO(layout, NULL, 0, "GRAPH_OT_insert"); + uiItemO(layout, NULL, 0, "GRAPH_OT_fmodifier_add"); + + uiItemS(layout); + + uiItemO(layout, NULL, 0, "GRAPH_OT_duplicate"); + uiItemO(layout, NULL, 0, "GRAPH_OT_delete"); + + uiItemS(layout); + + uiItemMenuF(layout, "Handle Type", 0, graph_edit_handlesmenu); + uiItemMenuF(layout, "Interpolation Mode", 0, graph_edit_ipomenu); + uiItemMenuF(layout, "Extrapolation Mode", 0, graph_edit_expomenu); + + uiItemS(layout); + + uiItemO(layout, NULL, 0, "GRAPH_OT_clean"); + uiItemO(layout, NULL, 0, "GRAPH_OT_sample"); + + uiItemS(layout); + + uiItemO(layout, NULL, 0, "GRAPH_OT_copy"); + uiItemO(layout, NULL, 0, "GRAPH_OT_paste"); +} + +/* ********************************************************* */ + enum { - B_REDR = 0, + B_REDR = 0, B_MODECHANGE, -} eActHeader_ButEvents; - -/* ************************ header area region *********************** */ - -static void do_viewmenu(bContext *C, void *arg, int event) -{ - SpaceIpo *sipo= (SpaceIpo *)CTX_wm_space_data(C); - - switch (event) { - case 1: /* Show time/frames */ - sipo->flag ^= SIPO_DRAWTIME; - break; - case 2: /* AutoMerge Keyframes */ - sipo->flag ^= SIPO_NOTRANSKEYCULL; - break; - case 3: /* Show/Hide handles */ - sipo->flag ^= SIPO_NOHANDLES; - break; - case 4: /* Show current frame number beside indicator */ - sipo->flag ^= SIPO_NODRAWCFRANUM; - break; - } -} - -static uiBlock *graph_viewmenu(bContext *C, ARegion *ar, void *arg_unused) -{ - ScrArea *curarea= CTX_wm_area(C); - SpaceIpo *sipo= (SpaceIpo *)CTX_wm_space_data(C); - uiBlock *block; - short yco= 0, menuwidth=120; - - block= uiBeginBlock(C, ar, "graph_viewmenu", UI_EMBOSSP); - uiBlockSetButmFunc(block, do_viewmenu, NULL); - - // XXX these options should use new menu-options - - if (sipo->flag & SIPO_DRAWTIME) { - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Show Frames|Ctrl T", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, ""); - } - else { - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Show Seconds|Ctrl T", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, ""); - } - - - uiDefIconTextBut(block, BUTM, 1, (sipo->flag & SIPO_NOTRANSKEYCULL)?ICON_CHECKBOX_DEHLT:ICON_CHECKBOX_HLT, - "AutoMerge Keyframes|", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, ""); - uiDefIconTextBut(block, BUTM, 1, (sipo->flag & SIPO_NOHANDLES)?ICON_CHECKBOX_DEHLT:ICON_CHECKBOX_HLT, - "Show Handles|Ctrl H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, ""); - uiDefIconTextBut(block, BUTM, 1, (sipo->flag & SIPO_NODRAWCFRANUM)?ICON_CHECKBOX_DEHLT:ICON_CHECKBOX_HLT, - "Show Current Frame Number|", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, ""); - - if (curarea->headertype==HEADERTOP) { - uiBlockSetDirection(block, UI_DOWN); - } - else { - uiBlockSetDirection(block, UI_TOP); - uiBlockFlipOrder(block); - } - - uiTextBoundsBlock(block, 50); - uiEndBlock(C, block); - - return block; -} +} eGraphEdit_Events; static void do_graph_buttons(bContext *C, void *arg, int event) { @@ -163,8 +263,19 @@ void graph_header_buttons(const bContext *C, ARegion *ar) int xmax; xmax= GetButStringLength("View"); - uiDefPulldownBut(block, graph_viewmenu, CTX_wm_area(C), - "View", xco, yco-2, xmax-3, 24, ""); + uiDefMenuBut(block, graph_viewmenu, NULL, "View", xco, yco, xmax-3, 20, ""); + xco+= xmax; + + xmax= GetButStringLength("Select"); + uiDefMenuBut(block, graph_selectmenu, NULL, "Select", xco, yco, xmax-3, 20, ""); + xco+= xmax; + + xmax= GetButStringLength("Channel"); + uiDefMenuBut(block, graph_channelmenu, NULL, "Channel", xco, yco, xmax-3, 20, ""); + xco+= xmax; + + xmax= GetButStringLength("Key"); + uiDefMenuBut(block, graph_editmenu, NULL, "Key", xco, yco, xmax-3, 20, ""); xco+= xmax; } @@ -202,8 +313,8 @@ void graph_header_buttons(const bContext *C, ARegion *ar) /* copy + paste */ uiBlockBeginAlign(block); - uiDefIconButO(block, BUT, "GRAPHEDIT_OT_keyframes_copy", WM_OP_INVOKE_REGION_WIN, ICON_COPYDOWN, xco+=XIC,yco,XIC,YIC, "Copies the selected keyframes from the selected channel(s) to the buffer"); - uiDefIconButO(block, BUT, "GRAPHEDIT_OT_keyframes_paste", WM_OP_INVOKE_REGION_WIN, ICON_PASTEDOWN, xco+=XIC,yco,XIC,YIC, "Pastes the keyframes from the buffer"); + uiDefIconButO(block, BUT, "GRAPH_OT_copy", WM_OP_INVOKE_REGION_WIN, ICON_COPYDOWN, xco+=XIC,yco,XIC,YIC, "Copies the selected keyframes from the selected channel(s) to the buffer"); + uiDefIconButO(block, BUT, "GRAPH_OT_paste", WM_OP_INVOKE_REGION_WIN, ICON_PASTEDOWN, xco+=XIC,yco,XIC,YIC, "Pastes the keyframes from the buffer"); uiBlockEndAlign(block); xco += (XIC + 8); @@ -225,9 +336,9 @@ void graph_header_buttons(const bContext *C, ARegion *ar) /* ghost curves */ // XXX these icons need to be changed if (sipo->ghostCurves.first) - uiDefIconButO(block, BUT, "GRAPHEDIT_OT_ghost_curves_clear", WM_OP_INVOKE_REGION_WIN, ICON_OUTLINER_DATA_CURVE, xco,yco,XIC,YIC, "Clear F-Curve snapshots (Ghosts) for this Graph Editor instance"); + uiDefIconButO(block, BUT, "GRAPH_OT_ghost_curves_clear", WM_OP_INVOKE_REGION_WIN, ICON_OUTLINER_DATA_CURVE, xco,yco,XIC,YIC, "Clear F-Curve snapshots (Ghosts) for this Graph Editor instance"); else - uiDefIconButO(block, BUT, "GRAPHEDIT_OT_ghost_curves_create", WM_OP_INVOKE_REGION_WIN, ICON_OUTLINER_OB_CURVE, xco,yco,XIC,YIC, "Create snapshot (Ghosts) of selected F-Curves as background aid for this Graph Editor instance"); + uiDefIconButO(block, BUT, "GRAPH_OT_ghost_curves_create", WM_OP_INVOKE_REGION_WIN, ICON_OUTLINER_OB_CURVE, xco,yco,XIC,YIC, "Create snapshot (Ghosts) of selected F-Curves as background aid for this Graph Editor instance"); xco+= XIC; diff --git a/source/blender/editors/space_graph/graph_intern.h b/source/blender/editors/space_graph/graph_intern.h index 7ba636302a5..93e3df1c728 100644 --- a/source/blender/editors/space_graph/graph_intern.h +++ b/source/blender/editors/space_graph/graph_intern.h @@ -58,10 +58,10 @@ void graph_header_buttons(const bContext *C, struct ARegion *ar); /* ***************************************** */ /* graph_select.c */ -void GRAPHEDIT_OT_keyframes_select_all_toggle(struct wmOperatorType *ot); -void GRAPHEDIT_OT_keyframes_select_border(struct wmOperatorType *ot); -void GRAPHEDIT_OT_keyframes_columnselect(struct wmOperatorType *ot); -void GRAPHEDIT_OT_keyframes_clickselect(struct wmOperatorType *ot); +void GRAPH_OT_select_all_toggle(struct wmOperatorType *ot); +void GRAPH_OT_select_border(struct wmOperatorType *ot); +void GRAPH_OT_select_column(struct wmOperatorType *ot); +void GRAPH_OT_clickselect(struct wmOperatorType *ot); /* defines for left-right select tool */ enum { @@ -82,28 +82,28 @@ enum { /* ***************************************** */ /* graph_edit.c */ -void GRAPHEDIT_OT_previewrange_set(struct wmOperatorType *ot); -void GRAPHEDIT_OT_view_all(struct wmOperatorType *ot); +void GRAPH_OT_previewrange_set(struct wmOperatorType *ot); +void GRAPH_OT_view_all(struct wmOperatorType *ot); -void GRAPHEDIT_OT_keyframes_click_insert(struct wmOperatorType *ot); +void GRAPH_OT_click_insert(struct wmOperatorType *ot); -void GRAPHEDIT_OT_keyframes_copy(struct wmOperatorType *ot); -void GRAPHEDIT_OT_keyframes_paste(struct wmOperatorType *ot); +void GRAPH_OT_copy(struct wmOperatorType *ot); +void GRAPH_OT_paste(struct wmOperatorType *ot); -void GRAPHEDIT_OT_keyframes_duplicate(struct wmOperatorType *ot); -void GRAPHEDIT_OT_keyframes_delete(struct wmOperatorType *ot); -void GRAPHEDIT_OT_keyframes_clean(struct wmOperatorType *ot); -void GRAPHEDIT_OT_keyframes_sample(struct wmOperatorType *ot); -void GRAPHEDIT_OT_keyframes_bake(struct wmOperatorType *ot); -void GRAPHEDIT_OT_keyframes_smooth(struct wmOperatorType *ot); +void GRAPH_OT_duplicate(struct wmOperatorType *ot); +void GRAPH_OT_delete(struct wmOperatorType *ot); +void GRAPH_OT_clean(struct wmOperatorType *ot); +void GRAPH_OT_sample(struct wmOperatorType *ot); +void GRAPH_OT_bake(struct wmOperatorType *ot); +void GRAPH_OT_smooth(struct wmOperatorType *ot); -void GRAPHEDIT_OT_keyframes_handletype(struct wmOperatorType *ot); -void GRAPHEDIT_OT_keyframes_interpolation_type(struct wmOperatorType *ot); -void GRAPHEDIT_OT_keyframes_extrapolation_type(struct wmOperatorType *ot); +void GRAPH_OT_handletype(struct wmOperatorType *ot); +void GRAPH_OT_interpolation_type(struct wmOperatorType *ot); +void GRAPH_OT_extrapolation_type(struct wmOperatorType *ot); -void GRAPHEDIT_OT_keyframes_cfrasnap(struct wmOperatorType *ot); -void GRAPHEDIT_OT_keyframes_snap(struct wmOperatorType *ot); -void GRAPHEDIT_OT_keyframes_mirror(struct wmOperatorType *ot); +void GRAPH_OT_frame_jump(struct wmOperatorType *ot); +void GRAPH_OT_snap(struct wmOperatorType *ot); +void GRAPH_OT_mirror(struct wmOperatorType *ot); /* defines for snap keyframes * NOTE: keep in sync with eEditKeyframes_Snap (in ED_keyframes_edit.h) @@ -128,16 +128,16 @@ enum { /* ----------- */ -void GRAPHEDIT_OT_fmodifier_add(struct wmOperatorType *ot); +void GRAPH_OT_fmodifier_add(struct wmOperatorType *ot); /* ----------- */ -void GRAPHEDIT_OT_ghost_curves_create(struct wmOperatorType *ot); -void GRAPHEDIT_OT_ghost_curves_clear(struct wmOperatorType *ot); +void GRAPH_OT_ghost_curves_create(struct wmOperatorType *ot); +void GRAPH_OT_ghost_curves_clear(struct wmOperatorType *ot); /* ***************************************** */ /* graph_buttons.c */ -void GRAPHEDIT_OT_properties(struct wmOperatorType *ot); +void GRAPH_OT_properties(struct wmOperatorType *ot); void graph_buttons_register(struct ARegionType *art); struct bAnimListElem *get_active_fcurve_channel(struct bAnimContext *ac); diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c index a23f0081c04..f7799023f34 100644 --- a/source/blender/editors/space_graph/graph_ops.c +++ b/source/blender/editors/space_graph/graph_ops.c @@ -58,6 +58,10 @@ #include "WM_api.h" #include "WM_types.h" +/* ************************** poll callbacks **********************************/ + + + /* ************************** view-based operators **********************************/ // XXX this probably shouldn't be here.. @@ -80,11 +84,11 @@ static int view_toggle_handles_exec (bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void GRAPHEDIT_OT_view_togglehandles (wmOperatorType *ot) +void GRAPH_OT_view_togglehandles (wmOperatorType *ot) { /* identification */ ot->name= "Show/Hide All Handles"; - ot->idname= "GRAPHEDIT_OT_handles_view_toggle"; + ot->idname= "GRAPH_OT_handles_view_toggle"; /* callbacks */ ot->exec= view_toggle_handles_exec; @@ -96,45 +100,43 @@ void GRAPHEDIT_OT_view_togglehandles (wmOperatorType *ot) void graphedit_operatortypes(void) { /* view */ - WM_operatortype_append(GRAPHEDIT_OT_view_togglehandles); - WM_operatortype_append(GRAPHEDIT_OT_previewrange_set); - WM_operatortype_append(GRAPHEDIT_OT_view_all); - WM_operatortype_append(GRAPHEDIT_OT_properties); + WM_operatortype_append(GRAPH_OT_view_togglehandles); + WM_operatortype_append(GRAPH_OT_previewrange_set); + WM_operatortype_append(GRAPH_OT_view_all); + WM_operatortype_append(GRAPH_OT_properties); - WM_operatortype_append(GRAPHEDIT_OT_ghost_curves_create); - WM_operatortype_append(GRAPHEDIT_OT_ghost_curves_clear); + WM_operatortype_append(GRAPH_OT_ghost_curves_create); + WM_operatortype_append(GRAPH_OT_ghost_curves_clear); /* keyframes */ /* selection */ - WM_operatortype_append(GRAPHEDIT_OT_keyframes_clickselect); - WM_operatortype_append(GRAPHEDIT_OT_keyframes_select_all_toggle); - WM_operatortype_append(GRAPHEDIT_OT_keyframes_select_border); - WM_operatortype_append(GRAPHEDIT_OT_keyframes_columnselect); + WM_operatortype_append(GRAPH_OT_clickselect); + WM_operatortype_append(GRAPH_OT_select_all_toggle); + WM_operatortype_append(GRAPH_OT_select_border); + WM_operatortype_append(GRAPH_OT_select_column); /* editing */ - WM_operatortype_append(GRAPHEDIT_OT_keyframes_snap); - WM_operatortype_append(GRAPHEDIT_OT_keyframes_mirror); - WM_operatortype_append(GRAPHEDIT_OT_keyframes_cfrasnap); - WM_operatortype_append(GRAPHEDIT_OT_keyframes_handletype); - WM_operatortype_append(GRAPHEDIT_OT_keyframes_interpolation_type); - WM_operatortype_append(GRAPHEDIT_OT_keyframes_extrapolation_type); - WM_operatortype_append(GRAPHEDIT_OT_keyframes_sample); - WM_operatortype_append(GRAPHEDIT_OT_keyframes_bake); - WM_operatortype_append(GRAPHEDIT_OT_keyframes_smooth); - WM_operatortype_append(GRAPHEDIT_OT_keyframes_clean); - WM_operatortype_append(GRAPHEDIT_OT_keyframes_delete); - WM_operatortype_append(GRAPHEDIT_OT_keyframes_duplicate); + WM_operatortype_append(GRAPH_OT_snap); + WM_operatortype_append(GRAPH_OT_mirror); + WM_operatortype_append(GRAPH_OT_frame_jump); + WM_operatortype_append(GRAPH_OT_handletype); + WM_operatortype_append(GRAPH_OT_interpolation_type); + WM_operatortype_append(GRAPH_OT_extrapolation_type); + WM_operatortype_append(GRAPH_OT_sample); + WM_operatortype_append(GRAPH_OT_bake); + WM_operatortype_append(GRAPH_OT_smooth); + WM_operatortype_append(GRAPH_OT_clean); + WM_operatortype_append(GRAPH_OT_delete); + WM_operatortype_append(GRAPH_OT_duplicate); - WM_operatortype_append(GRAPHEDIT_OT_keyframes_copy); - WM_operatortype_append(GRAPHEDIT_OT_keyframes_paste); + WM_operatortype_append(GRAPH_OT_copy); + WM_operatortype_append(GRAPH_OT_paste); - WM_operatortype_append(GRAPHEDIT_OT_keyframes_click_insert); - - //TODO: insertkey... + WM_operatortype_append(GRAPH_OT_click_insert); /* F-Curve Modifiers */ // XXX temporary? - WM_operatortype_append(GRAPHEDIT_OT_fmodifier_add); + WM_operatortype_append(GRAPH_OT_fmodifier_add); } /* ************************** registration - keymaps **********************************/ @@ -144,81 +146,82 @@ static void graphedit_keymap_keyframes (wmWindowManager *wm, ListBase *keymap) wmKeymapItem *kmi; /* view */ - WM_keymap_add_item(keymap, "GRAPHEDIT_OT_handles_view_toggle", HKEY, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "GRAPH_OT_handles_view_toggle", HKEY, KM_PRESS, KM_CTRL, 0); /* graph_select.c - selection tools */ /* click-select */ - WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_clickselect", SELECTMOUSE, KM_PRESS, 0, 0); - kmi= WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_clickselect", SELECTMOUSE, KM_PRESS, KM_ALT, 0); + WM_keymap_add_item(keymap, "GRAPH_OT_clickselect", SELECTMOUSE, KM_PRESS, 0, 0); + kmi= WM_keymap_add_item(keymap, "GRAPH_OT_clickselect", SELECTMOUSE, KM_PRESS, KM_ALT, 0); RNA_boolean_set(kmi->ptr, "column", 1); - kmi= WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_clickselect", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0); + kmi= WM_keymap_add_item(keymap, "GRAPH_OT_clickselect", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0); RNA_boolean_set(kmi->ptr, "extend", 1); - kmi= WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_clickselect", SELECTMOUSE, KM_PRESS, KM_ALT|KM_SHIFT, 0); + kmi= WM_keymap_add_item(keymap, "GRAPH_OT_clickselect", SELECTMOUSE, KM_PRESS, KM_ALT|KM_SHIFT, 0); RNA_boolean_set(kmi->ptr, "extend", 1); RNA_boolean_set(kmi->ptr, "column", 1); - kmi= WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_clickselect", SELECTMOUSE, KM_PRESS, KM_CTRL, 0); + kmi= WM_keymap_add_item(keymap, "GRAPH_OT_clickselect", SELECTMOUSE, KM_PRESS, KM_CTRL, 0); RNA_enum_set(kmi->ptr, "left_right", GRAPHKEYS_LRSEL_TEST); - kmi= WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_clickselect", SELECTMOUSE, KM_PRESS, KM_CTRL|KM_ALT, 0); + kmi= WM_keymap_add_item(keymap, "GRAPH_OT_clickselect", SELECTMOUSE, KM_PRESS, KM_CTRL|KM_ALT, 0); RNA_boolean_set(kmi->ptr, "curves", 1); - kmi= WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_clickselect", SELECTMOUSE, KM_PRESS, KM_CTRL|KM_ALT|KM_SHIFT, 0); + kmi= WM_keymap_add_item(keymap, "GRAPH_OT_clickselect", SELECTMOUSE, KM_PRESS, KM_CTRL|KM_ALT|KM_SHIFT, 0); RNA_boolean_set(kmi->ptr, "curves", 1); RNA_boolean_set(kmi->ptr, "extend", 1); /* deselect all */ - WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_select_all_toggle", AKEY, KM_PRESS, 0, 0); - RNA_boolean_set(WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_select_all_toggle", IKEY, KM_PRESS, KM_CTRL, 0)->ptr, "invert", 1); + WM_keymap_add_item(keymap, "GRAPH_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0); + RNA_boolean_set(WM_keymap_add_item(keymap, "GRAPH_OT_select_all_toggle", IKEY, KM_PRESS, KM_CTRL, 0)->ptr, "invert", 1); /* borderselect */ - WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_select_border", BKEY, KM_PRESS, 0, 0); - RNA_boolean_set(WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_select_border", BKEY, KM_PRESS, KM_ALT, 0)->ptr, "axis_range", 1); + WM_keymap_add_item(keymap, "GRAPH_OT_select_border", BKEY, KM_PRESS, 0, 0); + RNA_boolean_set(WM_keymap_add_item(keymap, "GRAPH_OT_select_border", BKEY, KM_PRESS, KM_ALT, 0)->ptr, "axis_range", 1); /* column select */ // XXX KKEY would be nice to keep for 'keyframe' lines - RNA_enum_set(WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_columnselect", KKEY, KM_PRESS, 0, 0)->ptr, "mode", GRAPHKEYS_COLUMNSEL_KEYS); - RNA_enum_set(WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_columnselect", KKEY, KM_PRESS, KM_CTRL, 0)->ptr, "mode", GRAPHKEYS_COLUMNSEL_CFRA); - RNA_enum_set(WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_columnselect", KKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "mode", GRAPHKEYS_COLUMNSEL_MARKERS_COLUMN); - RNA_enum_set(WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_columnselect", KKEY, KM_PRESS, KM_ALT, 0)->ptr, "mode", GRAPHKEYS_COLUMNSEL_MARKERS_BETWEEN); + RNA_enum_set(WM_keymap_add_item(keymap, "GRAPH_OT_select_column", KKEY, KM_PRESS, 0, 0)->ptr, "mode", GRAPHKEYS_COLUMNSEL_KEYS); + RNA_enum_set(WM_keymap_add_item(keymap, "GRAPH_OT_select_column", KKEY, KM_PRESS, KM_CTRL, 0)->ptr, "mode", GRAPHKEYS_COLUMNSEL_CFRA); + RNA_enum_set(WM_keymap_add_item(keymap, "GRAPH_OT_select_column", KKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "mode", GRAPHKEYS_COLUMNSEL_MARKERS_COLUMN); + RNA_enum_set(WM_keymap_add_item(keymap, "GRAPH_OT_select_column", KKEY, KM_PRESS, KM_ALT, 0)->ptr, "mode", GRAPHKEYS_COLUMNSEL_MARKERS_BETWEEN); /* graph_edit.c */ /* snap - current frame to selected keys */ - WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_cfrasnap", SKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0); + // TODO: maybe since this is called jump, we're better to have it on -J? + WM_keymap_add_item(keymap, "GRAPH_OT_frame_jump", SKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0); /* menu + single-step transform */ - WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_snap", SKEY, KM_PRESS, KM_SHIFT, 0); - WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_mirror", MKEY, KM_PRESS, KM_SHIFT, 0); + WM_keymap_add_item(keymap, "GRAPH_OT_snap", SKEY, KM_PRESS, KM_SHIFT, 0); + WM_keymap_add_item(keymap, "GRAPH_OT_mirror", MKEY, KM_PRESS, KM_SHIFT, 0); - WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_handletype", HKEY, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_interpolation_type", TKEY, KM_PRESS, KM_SHIFT, 0); - WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_extrapolation_type", EKEY, KM_PRESS, KM_SHIFT, 0); + WM_keymap_add_item(keymap, "GRAPH_OT_handletype", HKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "GRAPH_OT_interpolation_type", TKEY, KM_PRESS, KM_SHIFT, 0); + WM_keymap_add_item(keymap, "GRAPH_OT_extrapolation_type", EKEY, KM_PRESS, KM_SHIFT, 0); /* destructive */ - WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_clean", OKEY, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_smooth", OKEY, KM_PRESS, KM_ALT, 0); - WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_sample", OKEY, KM_PRESS, KM_SHIFT, 0); + WM_keymap_add_item(keymap, "GRAPH_OT_clean", OKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "GRAPH_OT_smooth", OKEY, KM_PRESS, KM_ALT, 0); + WM_keymap_add_item(keymap, "GRAPH_OT_sample", OKEY, KM_PRESS, KM_SHIFT, 0); - WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_bake", CKEY, KM_PRESS, KM_ALT, 0); + WM_keymap_add_item(keymap, "GRAPH_OT_bake", CKEY, KM_PRESS, KM_ALT, 0); - WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_delete", XKEY, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_delete", DELKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "GRAPH_OT_delete", XKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "GRAPH_OT_delete", DELKEY, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_duplicate", DKEY, KM_PRESS, KM_SHIFT, 0); + WM_keymap_add_item(keymap, "GRAPH_OT_duplicate", DKEY, KM_PRESS, KM_SHIFT, 0); /* insertkey */ - WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_click_insert", LEFTMOUSE, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "GRAPH_OT_click_insert", LEFTMOUSE, KM_PRESS, KM_CTRL, 0); /* copy/paste */ - WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_copy", CKEY, KM_PRESS, KM_CTRL, 0); - WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_paste", VKEY, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "GRAPH_OT_copy", CKEY, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "GRAPH_OT_paste", VKEY, KM_PRESS, KM_CTRL, 0); /* auto-set range */ - WM_keymap_add_item(keymap, "GRAPHEDIT_OT_previewrange_set", PKEY, KM_PRESS, KM_CTRL|KM_ALT, 0); - WM_keymap_add_item(keymap, "GRAPHEDIT_OT_view_all", HOMEKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "GRAPH_OT_previewrange_set", PKEY, KM_PRESS, KM_CTRL|KM_ALT, 0); + WM_keymap_add_item(keymap, "GRAPH_OT_view_all", HOMEKEY, KM_PRESS, 0, 0); /* F-Curve Modifiers */ // XXX these are temporary? operators... - WM_keymap_add_item(keymap, "GRAPHEDIT_OT_fmodifier_add", MKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0); + WM_keymap_add_item(keymap, "GRAPH_OT_fmodifier_add", MKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0); /* transform system */ @@ -233,7 +236,7 @@ void graphedit_keymap(wmWindowManager *wm) /* keymap for all regions */ keymap= WM_keymap_listbase(wm, "GraphEdit Generic", SPACE_IPO, 0); - WM_keymap_add_item(keymap, "GRAPHEDIT_OT_properties", NKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "GRAPH_OT_properties", NKEY, KM_PRESS, 0, 0); /* channels */ /* Channels are not directly handled by the Graph Editor module, but are inherited from the Animation module. diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c index a222109b0fe..632ce30863d 100644 --- a/source/blender/editors/space_graph/graph_select.c +++ b/source/blender/editors/space_graph/graph_select.c @@ -173,11 +173,11 @@ static int graphkeys_deselectall_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void GRAPHEDIT_OT_keyframes_select_all_toggle (wmOperatorType *ot) +void GRAPH_OT_select_all_toggle (wmOperatorType *ot) { /* identifiers */ ot->name= "Select All"; - ot->idname= "GRAPHEDIT_OT_keyframes_select_all_toggle"; + ot->idname= "GRAPH_OT_select_all_toggle"; /* api callbacks */ ot->exec= graphkeys_deselectall_exec; @@ -304,11 +304,11 @@ static int graphkeys_borderselect_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void GRAPHEDIT_OT_keyframes_select_border(wmOperatorType *ot) +void GRAPH_OT_select_border(wmOperatorType *ot) { /* identifiers */ ot->name= "Border Select"; - ot->idname= "GRAPHEDIT_OT_keyframes_select_border"; + ot->idname= "GRAPH_OT_select_border"; /* api callbacks */ ot->invoke= WM_border_select_invoke; @@ -497,11 +497,11 @@ static int graphkeys_columnselect_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void GRAPHEDIT_OT_keyframes_columnselect (wmOperatorType *ot) +void GRAPH_OT_select_column (wmOperatorType *ot) { /* identifiers */ ot->name= "Select All"; - ot->idname= "GRAPHEDIT_OT_keyframes_columnselect"; + ot->idname= "GRAPH_OT_select_column"; /* api callbacks */ ot->exec= graphkeys_columnselect_exec; @@ -908,11 +908,11 @@ static int graphkeys_clickselect_invoke(bContext *C, wmOperator *op, wmEvent *ev return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH; } -void GRAPHEDIT_OT_keyframes_clickselect (wmOperatorType *ot) +void GRAPH_OT_clickselect (wmOperatorType *ot) { /* identifiers */ ot->name= "Mouse Select Keys"; - ot->idname= "GRAPHEDIT_OT_keyframes_clickselect"; + ot->idname= "GRAPH_OT_clickselect"; /* api callbacks */ ot->invoke= graphkeys_clickselect_invoke; From b4acd77526f32faab0c3d86436eef56096985c3d Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 23 Jun 2009 13:25:31 +0000 Subject: [PATCH 054/114] NLA SoC: Big Commit - Restored NLA-Mapping Corrections In TweakMode, the keyframes of the Active Action are now shown (and can be edited) in NLA-mapped time, with appropriate corrections applied when editing. This works in the DopeSheet and Graph Editors :) To do this, got rid of the old wrappers/API-methods, replacing them with new-style ones. A few methods previously (in this branch) used only for evaluation are now used for this purpose too. As the same code is used for editing + evaluation, this should now be much better to work with. I've only done a few brief tests now, but I think I might've muddled the invert-flags on one or two cases which I'll need to check out tomorrow. So, beware that there may be some weird and critical bugs for the next few days here... Also, added proper license headers to new NLA files. TODO: - testing + bugfixing due to this commit - show range of keyframes in NLA Editor active-action line --- source/blender/blenkernel/BKE_action.h | 6 - source/blender/blenkernel/BKE_nla.h | 2 + source/blender/blenkernel/intern/action.c | 42 ----- source/blender/blenkernel/intern/anim_sys.c | 158 ++++-------------- source/blender/blenkernel/intern/fcurve.c | 29 +++- source/blender/blenkernel/intern/nla.c | 136 +++++++++++++++ source/blender/blenkernel/nla_private.h | 78 +++++++++ source/blender/blenloader/intern/readfile.c | 4 + source/blender/editors/animation/anim_draw.c | 72 ++++---- .../editors/animation/keyframes_draw.c | 18 +- source/blender/editors/include/ED_anim_api.h | 14 +- .../editors/include/ED_keyframes_draw.h | 5 +- .../editors/space_action/action_draw.c | 24 +-- .../editors/space_action/action_edit.c | 48 +++--- .../editors/space_action/action_select.c | 45 ++--- .../blender/editors/space_graph/graph_draw.c | 10 +- .../blender/editors/space_graph/graph_edit.c | 51 ++++-- .../editors/space_graph/graph_select.c | 46 +++-- source/blender/editors/transform/transform.c | 58 +++---- .../editors/transform/transform_conversions.c | 103 +++++++----- .../editors/transform/transform_generics.c | 31 ---- source/blender/makesdna/DNA_anim_types.h | 29 +++- 22 files changed, 569 insertions(+), 440 deletions(-) create mode 100644 source/blender/blenkernel/nla_private.h diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index 1fb200b94a8..0c9bba5e413 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -148,12 +148,6 @@ void copy_pose_result(struct bPose *to, struct bPose *from); /* clear all transforms */ void rest_pose(struct bPose *pose); -/* map global time (frame nr) to strip converted time, doesn't clip */ -float get_action_frame(struct Object *ob, float cframe); -/* map strip time to global time (frame nr) */ -float get_action_frame_inv(struct Object *ob, float cframe); - - /* functions used by the game engine */ void game_copy_pose(struct bPose **dst, struct bPose *src); void game_free_pose(struct bPose *pose); diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index 5200ca6d4d7..cc73ac02690 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -73,5 +73,7 @@ void BKE_nla_action_pushdown(struct AnimData *adt); short BKE_nla_tweakmode_enter(struct AnimData *adt); void BKE_nla_tweakmode_exit(struct AnimData *adt); +float BKE_nla_tweakedit_remap(struct AnimData *adt, float cframe, short invert); + #endif diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index f88e249d38c..96896509f60 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -769,48 +769,6 @@ void framechange_poses_clear_unkeyed(void) /* ************** time ****************** */ -static bActionStrip *get_active_strip(Object *ob) -{ -#if 0 // XXX old animation system - bActionStrip *strip; - - if(ob->action==NULL) - return NULL; - - for (strip=ob->nlastrips.first; strip; strip=strip->next) - if(strip->flag & ACTSTRIP_ACTIVE) - break; - - if(strip && strip->act==ob->action) - return strip; -#endif // XXX old animation system - - return NULL; -} - -/* if the conditions match, it converts current time to strip time */ -// TODO: change this adt -float get_action_frame(Object *ob, float cframe) -{ - bActionStrip *strip= get_active_strip(ob); - - //if(strip) - // return get_actionstrip_frame(strip, cframe, 0); - return cframe; -} - -/* inverted, strip time to current time */ -// TODO: change this to adt -float get_action_frame_inv(Object *ob, float cframe) -{ - bActionStrip *strip= get_active_strip(ob); - - //if(strip) - // return get_actionstrip_frame(strip, cframe, 1); - return cframe; -} - - /* Check if the given action has any keyframes */ short action_has_motion(const bAction *act) { diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 7a6706b7c5a..877353a85e9 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -1,5 +1,30 @@ -/* Testing code for new animation system in 2.5 - * Copyright 2009, Joshua Leung +/** + * $Id: anim_sys.c 21023 2009-06-20 04:02:49Z aligorith $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Joshua Leung (full recode) + * + * ***** END GPL LICENSE BLOCK ***** */ #include @@ -14,6 +39,8 @@ #include "BLI_arithb.h" #include "BLI_dynstr.h" +#include "DNA_anim_types.h" + #include "BKE_animsys.h" #include "BKE_action.h" #include "BKE_fcurve.h" @@ -25,7 +52,7 @@ #include "RNA_access.h" #include "RNA_types.h" -#include "DNA_anim_types.h" +#include "nla_private.h" /* ***************************************** */ /* AnimData API */ @@ -549,129 +576,6 @@ void animsys_evaluate_action (PointerRNA *ptr, bAction *act, AnimMapper *remap, /* ***************************************** */ /* NLA System - Evaluation */ -/* used for list of strips to accumulate at current time */ -typedef struct NlaEvalStrip { - struct NlaEvalStrip *next, *prev; - - NlaTrack *track; /* track that this strip belongs to */ - NlaStrip *strip; /* strip that's being used */ - - short track_index; /* the index of the track within the list */ - short strip_mode; /* which end of the strip are we looking at */ - - float strip_time; /* time at which which strip is being evaluated */ -} NlaEvalStrip; - -/* NlaEvalStrip->strip_mode */ -enum { - /* standard evaluation */ - NES_TIME_BEFORE = -1, - NES_TIME_WITHIN, - NES_TIME_AFTER, - - /* transition-strip evaluations */ - NES_TIME_TRANSITION_START, - NES_TIME_TRANSITION_END, -} eNlaEvalStrip_StripMode; - - -/* temp channel for accumulating data from NLA (avoids needing to clear all values first) */ -// TODO: maybe this will be used as the 'cache' stuff needed for editable values too? -typedef struct NlaEvalChannel { - struct NlaEvalChannel *next, *prev; - - PointerRNA ptr; /* pointer to struct containing property to use */ - PropertyRNA *prop; /* RNA-property type to use (should be in the struct given) */ - int index; /* array index (where applicable) */ - - float value; /* value of this channel */ -} NlaEvalChannel; - - -/* ---------------------- */ - -/* non clipped mapping for strip-time <-> global time (for Action-Clips) - * invert = convert action-strip time to global time - */ -static float nlastrip_get_frame_actionclip (NlaStrip *strip, float cframe, short invert) -{ - float length, actlength, repeat, scale; - - /* get number of repeats */ - if (IS_EQ(strip->repeat, 0.0f)) strip->repeat = 1.0f; - repeat = strip->repeat; - - /* scaling */ - if (IS_EQ(strip->scale, 0.0f)) strip->scale= 1.0f; - scale = (float)fabs(strip->scale); /* scale must be positive - we've got a special flag for reversing */ - - /* length of referenced action */ - actlength = strip->actend - strip->actstart; - if (IS_EQ(actlength, 0.0f)) actlength = 1.0f; - - /* length of strip */ - length= actlength * scale * repeat; - if (IS_EQ(length, 0.0f)) length= strip->end - strip->start; - - /* reversed = play strip backwards */ - if (strip->flag & NLASTRIP_FLAG_REVERSE) { - /* invert = convert action-strip time to global time */ - if (invert) - return length*(strip->actend - cframe)/(repeat*actlength) + strip->start; - else - return strip->actend - repeat*actlength*(cframe - strip->start)/length; - } - else { - /* invert = convert action-strip time to global time */ - if (invert) - return length*(cframe - strip->actstart)/(repeat*actlength) + strip->start; - else - return repeat*actlength*(cframe - strip->start)/length + strip->actstart; - } -} - -/* non clipped mapping for strip-time <-> global time (for Transitions) - * invert = convert action-strip time to global time - */ -static float nlastrip_get_frame_transition (NlaStrip *strip, float cframe, short invert) -{ - float length; - - /* length of strip */ - length= strip->end - strip->start; - - /* reversed = play strip backwards */ - if (strip->flag & NLASTRIP_FLAG_REVERSE) { - /* invert = convert within-strip-time to global time */ - if (invert) - return strip->end - (length * cframe); - else - return (strip->end - cframe) / length; - } - else { - /* invert = convert within-strip-time to global time */ - if (invert) - return (length * cframe) + strip->start; - else - return (cframe - strip->start) / length; - } -} - -/* non clipped mapping for strip-time <-> global time - * invert = convert action-strip time to global time - */ -static float nlastrip_get_frame (NlaStrip *strip, float cframe, short invert) -{ - switch (strip->type) { - case NLASTRIP_TYPE_TRANSITION: /* transition */ - return nlastrip_get_frame_transition(strip, cframe, invert); - - case NLASTRIP_TYPE_CLIP: /* action-clip (default) */ - default: - return nlastrip_get_frame_actionclip(strip, cframe, invert); - } -} - /* calculate influence of strip based for given frame based on blendin/out values */ static float nlastrip_get_influence (NlaStrip *strip, float cframe) { @@ -695,7 +599,7 @@ static float nlastrip_get_influence (NlaStrip *strip, float cframe) } /* evaluate the evaluation time and influence for the strip, storing the results in the strip */ -void nlastrip_evaluate_controls (NlaStrip *strip, float ctime) +static void nlastrip_evaluate_controls (NlaStrip *strip, float ctime) { /* firstly, analytically generate values for influence and time (if applicable) */ if ((strip->flag & NLASTRIP_FLAG_USR_TIME) == 0) diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 856930e5a44..27ca6332cdc 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -1,5 +1,30 @@ -/* Testing code for new animation system in 2.5 - * Copyright 2009, Joshua Leung +/** + * $Id: fcurve.c 21023 2009-06-20 04:02:49Z aligorith $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Joshua Leung (full recode) + * + * ***** END GPL LICENSE BLOCK ***** */ diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 1ce6d9f98c7..a5b3b59d310 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -49,6 +49,9 @@ #include "BKE_object.h" #include "BKE_utildefines.h" +#include "RNA_access.h" +#include "nla_private.h" + #ifdef HAVE_CONFIG_H #include @@ -318,6 +321,135 @@ NlaStrip *add_nlastrip_to_stack (AnimData *adt, bAction *act) return strip; } +/* *************************************************** */ +/* NLA Evaluation <-> Editing Stuff */ + +/* Strip Mapping ------------------------------------- */ + +/* non clipped mapping for strip-time <-> global time (for Action-Clips) + * invert = convert action-strip time to global time + */ +static float nlastrip_get_frame_actionclip (NlaStrip *strip, float cframe, short invert) +{ + float length, actlength, repeat, scale; + + /* get number of repeats */ + if (IS_EQ(strip->repeat, 0.0f)) strip->repeat = 1.0f; + repeat = strip->repeat; + + /* scaling */ + if (IS_EQ(strip->scale, 0.0f)) strip->scale= 1.0f; + scale = (float)fabs(strip->scale); /* scale must be positive - we've got a special flag for reversing */ + + /* length of referenced action */ + actlength = strip->actend - strip->actstart; + if (IS_EQ(actlength, 0.0f)) actlength = 1.0f; + + /* length of strip */ + length= actlength * scale * repeat; + if (IS_EQ(length, 0.0f)) length= strip->end - strip->start; + + /* reversed = play strip backwards */ + if (strip->flag & NLASTRIP_FLAG_REVERSE) { + /* invert = convert action-strip time to global time */ + if (invert) + return length*(strip->actend - cframe)/(repeat*actlength) + strip->start; + else + return strip->actend - repeat*actlength*(cframe - strip->start)/length; + } + else { + /* invert = convert action-strip time to global time */ + if (invert) + return length*(cframe - strip->actstart)/(repeat*actlength) + strip->start; + else + return repeat*actlength*(cframe - strip->start)/length + strip->actstart; + } +} + +/* non clipped mapping for strip-time <-> global time (for Transitions) + * invert = convert action-strip time to global time + */ +static float nlastrip_get_frame_transition (NlaStrip *strip, float cframe, short invert) +{ + float length; + + /* length of strip */ + length= strip->end - strip->start; + + /* reversed = play strip backwards */ + if (strip->flag & NLASTRIP_FLAG_REVERSE) { + /* invert = convert within-strip-time to global time */ + if (invert) + return strip->end - (length * cframe); + else + return (strip->end - cframe) / length; + } + else { + /* invert = convert within-strip-time to global time */ + if (invert) + return (length * cframe) + strip->start; + else + return (cframe - strip->start) / length; + } +} + +/* non clipped mapping for strip-time <-> global time + * invert = convert action-strip time to global time + * + * only secure for 'internal' (i.e. within AnimSys evaluation) operations, + * but should not be directly relied on for stuff which interacts with editors + */ +float nlastrip_get_frame (NlaStrip *strip, float cframe, short invert) +{ + switch (strip->type) { + case NLASTRIP_TYPE_TRANSITION: /* transition */ + return nlastrip_get_frame_transition(strip, cframe, invert); + + case NLASTRIP_TYPE_CLIP: /* action-clip (default) */ + default: + return nlastrip_get_frame_actionclip(strip, cframe, invert); + } +} + + +/* Non clipped mapping for strip-time <-> global time + * invert = convert strip-time to global time + * + * Public API method - perform this mapping using the given AnimData block + * and perform any necessary sanity checks on the value + */ +float BKE_nla_tweakedit_remap (AnimData *adt, float cframe, short invert) +{ + NlaStrip *strip; + + /* sanity checks + * - obviously we've got to have some starting data + * - when not in tweakmode, the active Action does not have any scaling applied :) + */ + if ((adt == NULL) || (adt->flag & ADT_NLA_EDIT_ON)==0) + return cframe; + + /* if the active-strip info has been stored already, access this, otherwise look this up + * and store for (very probable) future usage + */ + if (adt->actstrip == NULL) { + NlaTrack *nlt= BKE_nlatrack_find_active(adt); + adt->actstrip= BKE_nlastrip_find_active(nlt); + } + strip= adt->actstrip; + + /* sanity checks + * - in rare cases, we may not be able to find this strip for some reason (internal error) + * - for now, if the user has defined a curve to control the time, this correction cannot be performed + * reliably... + */ + if ((strip == NULL) || (strip->flag & NLASTRIP_FLAG_USR_TIME)) + return cframe; + + /* perform the correction now... */ + return nlastrip_get_frame(strip, cframe, invert); +} + /* *************************************************** */ /* Basic Utilities */ @@ -693,9 +825,11 @@ short BKE_nla_tweakmode_enter (AnimData *adt) * - 'real' active action to temp storage (no need to change user-counts) * - action of active strip set to be the 'active action', and have its usercount incremented * - editing-flag for this AnimData block should also get turned on (for more efficient restoring) + * - take note of the active strip for mapping-correction of keyframes in the action being edited */ adt->tmpact= adt->action; adt->action= activeStrip->act; + adt->actstrip= activeStrip; id_us_plus(&activeStrip->act->id); adt->flag |= ADT_NLA_EDIT_ON; @@ -734,10 +868,12 @@ void BKE_nla_tweakmode_exit (AnimData *adt) * - 'real' active action is restored from storage * - storage pointer gets cleared (to avoid having bad notes hanging around) * - editing-flag for this AnimData block should also get turned off + * - clear pointer to active strip */ if (adt->action) adt->action->id.us--; adt->action= adt->tmpact; adt->tmpact= NULL; + adt->actstrip= NULL; adt->flag &= ~ADT_NLA_EDIT_ON; } diff --git a/source/blender/blenkernel/nla_private.h b/source/blender/blenkernel/nla_private.h new file mode 100644 index 00000000000..af886fb7de8 --- /dev/null +++ b/source/blender/blenkernel/nla_private.h @@ -0,0 +1,78 @@ +/** + * $Id: BKE_nla.h 20999 2009-06-19 04:45:56Z aligorith $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Joshua Leung (full recode) + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef NLA_PRIVATE +#define NLA_PRIVATE + +/* --------------- NLA Evaluation DataTypes ----------------------- */ + +/* used for list of strips to accumulate at current time */ +typedef struct NlaEvalStrip { + struct NlaEvalStrip *next, *prev; + + NlaTrack *track; /* track that this strip belongs to */ + NlaStrip *strip; /* strip that's being used */ + + short track_index; /* the index of the track within the list */ + short strip_mode; /* which end of the strip are we looking at */ + + float strip_time; /* time at which which strip is being evaluated */ +} NlaEvalStrip; + +/* NlaEvalStrip->strip_mode */ +enum { + /* standard evaluation */ + NES_TIME_BEFORE = -1, + NES_TIME_WITHIN, + NES_TIME_AFTER, + + /* transition-strip evaluations */ + NES_TIME_TRANSITION_START, + NES_TIME_TRANSITION_END, +} eNlaEvalStrip_StripMode; + + +/* temp channel for accumulating data from NLA (avoids needing to clear all values first) */ +// TODO: maybe this will be used as the 'cache' stuff needed for editable values too? +typedef struct NlaEvalChannel { + struct NlaEvalChannel *next, *prev; + + PointerRNA ptr; /* pointer to struct containing property to use */ + PropertyRNA *prop; /* RNA-property type to use (should be in the struct given) */ + int index; /* array index (where applicable) */ + + float value; /* value of this channel */ +} NlaEvalChannel; + +/* --------------- NLA Functions (not to be used as a proper API) ----------------------- */ + +/* convert from strip time <-> global time */ +float nlastrip_get_frame(NlaStrip *strip, float cframe, short invert); + +#endif // NLA_PRIVATE diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index af4f61fccc4..d7f60e1928b 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -1933,6 +1933,10 @@ static void direct_link_animdata(FileData *fd, AnimData *adt) /* link NLA-data */ link_list(fd, &adt->nla_tracks); direct_link_nladata(fd, &adt->nla_tracks); + + /* clear temp pointers that may have been set... */ + // TODO: it's probably only a small cost to reload this anyway... + adt->actstrip= NULL; } /* ************ READ NODE TREE *************** */ diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c index c176f20c26b..6d079fe148a 100644 --- a/source/blender/editors/animation/anim_draw.c +++ b/source/blender/editors/animation/anim_draw.c @@ -43,10 +43,12 @@ #include "BLI_blenlib.h" +#include "BKE_animsys.h" #include "BKE_action.h" #include "BKE_context.h" #include "BKE_global.h" #include "BKE_fcurve.h" +#include "BKE_nla.h" #include "BKE_object.h" #include "BKE_screen.h" #include "BKE_utildefines.h" @@ -232,37 +234,16 @@ void ANIM_draw_previewrange (const bContext *C, View2D *v2d) /* *************************************************** */ /* NLA-MAPPING UTILITIES (required for drawing and also editing keyframes) */ -/* Obtain the Object providing NLA-scaling for the given channel (if applicable) */ -Object *ANIM_nla_mapping_get(bAnimContext *ac, bAnimListElem *ale) +/* Obtain the AnimData block providing NLA-mapping for the given channel (if applicable) */ +AnimData *ANIM_nla_mapping_get(bAnimContext *ac, bAnimListElem *ale) { /* sanity checks */ if (ac == NULL) return NULL; /* handling depends on the type of animation-context we've got */ - if (ac->datatype == ANIMCONT_ACTION) { - /* Action Editor (action mode) or Graph Editor (ipo mode): - * Only use if editor is not pinned, and active object has action - */ - if (ac->obact && ac->obact->action) { - SpaceAction *saction= (SpaceAction *)ac->sa->spacedata.first; - - if (saction->pin == 0) - return ac->obact; - } - } - else if ((ac->datatype == ANIMCONT_DOPESHEET) && (ale)) { - /* Dopesheet: - * Only if channel is available, and is owned by an Object with an Action - */ - if ((ale->id) && (GS(ale->id->name) == ID_OB)) { - Object *ob= (Object *)ale->id; - - if (ob->action) - return ob; - } - } - // XXX todo: add F-Curves mode (Graph Editor) ... + if (ale && ale->id) + return BKE_animdata_from_id(ale->id); /* no appropriate object found */ return NULL; @@ -273,7 +254,8 @@ Object *ANIM_nla_mapping_get(bAnimContext *ac, bAnimListElem *ale) * (where this is called) is single-threaded anyway */ // XXX was called: map_active_strip() -void ANIM_nla_mapping_draw(gla2DDrawInfo *di, Object *ob, short restore) +// TODO: should this be depreceated? +void ANIM_nla_mapping_draw(gla2DDrawInfo *di, AnimData *adt, short restore) { static rctf stored; @@ -288,8 +270,8 @@ void ANIM_nla_mapping_draw(gla2DDrawInfo *di, Object *ob, short restore) gla2DGetMap(di, &stored); map= stored; - map.xmin= get_action_frame(ob, map.xmin); - map.xmax= get_action_frame(ob, map.xmax); + map.xmin= BKE_nla_tweakedit_remap(adt, map.xmin, 0); + map.xmax= BKE_nla_tweakedit_remap(adt, map.xmax, 0); if (map.xmin == map.xmax) map.xmax += 1.0f; gla2DSetMap(di, &map); @@ -298,36 +280,38 @@ void ANIM_nla_mapping_draw(gla2DDrawInfo *di, Object *ob, short restore) /* ------------------- */ -/* helper function for ANIM_nla_mapping_apply_ipocurve() -> "restore", i.e. mapping points back to IPO-time */ +/* helper function for ANIM_nla_mapping_apply_fcurve() -> "restore", i.e. mapping points back to action-time */ static short bezt_nlamapping_restore(BeztEditData *bed, BezTriple *bezt) { - /* object providing scaling is stored in 'data', only_keys option is stored in i1 */ - Object *ob= (Object *)bed->data; + /* AnimData block providing scaling is stored in 'data', only_keys option is stored in i1 */ + AnimData *adt= (AnimData *)bed->data; short only_keys= (short)bed->i1; /* adjust BezTriple handles only if allowed to */ if (only_keys == 0) { - bezt->vec[0][0]= get_action_frame(ob, bezt->vec[0][0]); - bezt->vec[2][0]= get_action_frame(ob, bezt->vec[2][0]); - } - bezt->vec[1][0]= get_action_frame(ob, bezt->vec[1][0]); + bezt->vec[0][0]= BKE_nla_tweakedit_remap(adt, bezt->vec[0][0], 0); + bezt->vec[2][0]= BKE_nla_tweakedit_remap(adt, bezt->vec[2][0], 0); + } + + bezt->vec[1][0]= BKE_nla_tweakedit_remap(adt, bezt->vec[1][0], 0); return 0; } -/* helper function for ANIM_nla_mapping_apply_ipocurve() -> "apply", i.e. mapping points to NLA-mapped global time */ +/* helper function for ANIM_nla_mapping_apply_fcurve() -> "apply", i.e. mapping points to NLA-mapped global time */ static short bezt_nlamapping_apply(BeztEditData *bed, BezTriple *bezt) { - /* object providing scaling is stored in 'data', only_keys option is stored in i1 */ - Object *ob= (Object *)bed->data; + /* AnimData block providing scaling is stored in 'data', only_keys option is stored in i1 */ + AnimData *adt= (AnimData *)bed->data; short only_keys= (short)bed->i1; /* adjust BezTriple handles only if allowed to */ if (only_keys == 0) { - bezt->vec[0][0]= get_action_frame_inv(ob, bezt->vec[0][0]); - bezt->vec[2][0]= get_action_frame_inv(ob, bezt->vec[2][0]); + bezt->vec[0][0]= BKE_nla_tweakedit_remap(adt, bezt->vec[0][0], 1); + bezt->vec[2][0]= BKE_nla_tweakedit_remap(adt, bezt->vec[2][0], 1); } - bezt->vec[1][0]= get_action_frame_inv(ob, bezt->vec[1][0]); + + bezt->vec[1][0]= BKE_nla_tweakedit_remap(adt, bezt->vec[1][0], 1); return 0; } @@ -338,17 +322,17 @@ static short bezt_nlamapping_apply(BeztEditData *bed, BezTriple *bezt) * - restore = whether to map points back to non-mapped time * - only_keys = whether to only adjust the location of the center point of beztriples */ -void ANIM_nla_mapping_apply_fcurve(Object *ob, FCurve *fcu, short restore, short only_keys) +void ANIM_nla_mapping_apply_fcurve (AnimData *adt, FCurve *fcu, short restore, short only_keys) { BeztEditData bed; BeztEditFunc map_cb; /* init edit data - * - ob is stored in 'data' + * - AnimData is stored in 'data' * - only_keys is stored in 'i1' */ memset(&bed, 0, sizeof(BeztEditData)); - bed.data= (void *)ob; + bed.data= (void *)adt; bed.i1= (int)only_keys; /* get editing callback */ diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c index 144cd68f6df..07db47c8fed 100644 --- a/source/blender/editors/animation/keyframes_draw.c +++ b/source/blender/editors/animation/keyframes_draw.c @@ -451,7 +451,7 @@ void ob_to_keylist(Object *ob, ListBase *keys, ListBase *blocks, ActKeysInc *aki /* Add action keyframes */ if (ob->adt && ob->adt->action) - action_nlascaled_to_keylist(ob, ob->adt->action, keys, blocks, aki); + action_nlascaled_to_keylist(ob->adt, ob->adt->action, keys, blocks, aki); /* Add shapekey keyframes (only if dopesheet allows, if it is available) */ // TODO: when we adapt NLA system, this needs to be the NLA-scaled version @@ -602,34 +602,34 @@ void action_to_keylist(bAction *act, ListBase *keys, ListBase *blocks, ActKeysIn } } -void action_nlascaled_to_keylist(Object *ob, bAction *act, ListBase *keys, ListBase *blocks, ActKeysInc *aki) +void action_nlascaled_to_keylist(AnimData *adt, bAction *act, ListBase *keys, ListBase *blocks, ActKeysInc *aki) { FCurve *fcu; - Object *oldob= NULL; + AnimData *oldadt= NULL; - /* although apply and clearing NLA-scaling pre-post creating keylist does impact on performance, + /* although apply and clearing NLA-mapping pre-post creating keylist does impact on performance, * the effects should be fairly minimal, as we're already going through the keyframes multiple times * already for blocks too... */ if (act) { /* if 'aki' is provided, store it's current ob to restore later as it might not be the same */ if (aki) { - oldob= aki->ob; - aki->ob= ob; + oldadt= aki->adt; + aki->adt= adt; } /* loop through F-Curves * - scaling correction only does times for center-points, so should be faster */ for (fcu= act->curves.first; fcu; fcu= fcu->next) { - ANIM_nla_mapping_apply_fcurve(ob, fcu, 0, 1); + ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 1); fcurve_to_keylist(fcu, keys, blocks, aki); - ANIM_nla_mapping_apply_fcurve(ob, fcu, 1, 1); + ANIM_nla_mapping_apply_fcurve(adt, fcu, 1, 1); } /* if 'aki' is provided, restore ob */ if (aki) - aki->ob= oldob; + aki->adt= oldadt; } } diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index 8c54c4e8f67..4bfcbde8f1e 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -310,16 +310,14 @@ void ipo_rainbow(int cur, int tot, float *out); /* ------------- NLA-Mapping ----------------------- */ /* anim_draw.c */ -// XXX these need attention for the new editing method... +/* Obtain the AnimData block providing NLA-scaling for the given channel if applicable */ +struct AnimData *ANIM_nla_mapping_get(bAnimContext *ac, bAnimListElem *ale); -/* Obtain the Object providing NLA-scaling for the given channel if applicable */ -struct Object *ANIM_nla_mapping_get(bAnimContext *ac, bAnimListElem *ale); +/* Set/clear temporary mapping of coordinates from 'local-action' time to 'global-nla-mapped' time */ +void ANIM_nla_mapping_draw(struct gla2DDrawInfo *di, struct AnimData *adt, short restore); -/* Set/clear temporary mapping of coordinates from 'local-action' time to 'global-nla-scaled' time */ -void ANIM_nla_mapping_draw(struct gla2DDrawInfo *di, struct Object *ob, short restore); - -/* Apply/Unapply NLA mapping to all keyframes in the nominated IPO block */ -void ANIM_nla_mapping_apply_fcurve(struct Object *ob, struct FCurve *fcu, short restore, short only_keys); +/* Apply/Unapply NLA mapping to all keyframes in the nominated F-Curve */ +void ANIM_nla_mapping_apply_fcurve(struct AnimData *adt, struct FCurve *fcu, short restore, short only_keys); /* ------------- Utility macros ----------------------- */ diff --git a/source/blender/editors/include/ED_keyframes_draw.h b/source/blender/editors/include/ED_keyframes_draw.h index 81420ac95e5..153b10cf832 100644 --- a/source/blender/editors/include/ED_keyframes_draw.h +++ b/source/blender/editors/include/ED_keyframes_draw.h @@ -30,6 +30,7 @@ #ifndef ED_KEYFRAMES_DRAW_H #define ED_KEYFRAMES_DRAW_H +struct AnimData; struct BezTriple; struct FCurve; struct gla2DDrawInfo; @@ -69,7 +70,7 @@ typedef struct ActKeyBlock { /* Inclusion-Range Limiting Struct (optional) */ typedef struct ActKeysInc { struct bDopeSheet *ads; /* dopesheet data (for dopesheet mode) */ - struct Object *ob; /* owner object for NLA-scaling info (if Object channels, is just Object) */ + struct AnimData *adt; /* owner for NLA-mapping info */ short actmode; /* mode of the Action Editor (-1 is for NLA) */ float start, end; /* frames (global-time) to only consider keys between */ // XXX not used anymore! @@ -89,7 +90,7 @@ void draw_gpl_channel(struct gla2DDrawInfo *di, ActKeysInc *aki, struct bGPDlaye void fcurve_to_keylist(struct FCurve *fcu, ListBase *keys, ListBase *blocks, ActKeysInc *aki); void agroup_to_keylist(struct bActionGroup *agrp, ListBase *keys, ListBase *blocks, ActKeysInc *aki); void action_to_keylist(struct bAction *act, ListBase *keys, ListBase *blocks, ActKeysInc *aki); -void action_nlascaled_to_keylist(struct Object *ob, struct bAction *act, ListBase *keys, ListBase *blocks, ActKeysInc *aki); +void action_nlascaled_to_keylist(struct AnimData *adt, struct bAction *act, ListBase *keys, ListBase *blocks, ActKeysInc *aki); void ob_to_keylist(struct Object *ob, ListBase *keys, ListBase *blocks, ActKeysInc *aki); void scene_to_keylist(struct Scene *sce, ListBase *keys, ListBase *blocks, ActKeysInc *aki); void gpl_to_keylist(struct bGPDlayer *gpl, ListBase *keys, ListBase *blocks, ActKeysInc *aki); diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c index 6eae581aa40..61048598644 100644 --- a/source/blender/editors/space_action/action_draw.c +++ b/source/blender/editors/space_action/action_draw.c @@ -964,7 +964,7 @@ ActKeysInc *init_aki_data(bAnimContext *ac, bAnimListElem *ale) return NULL; /* if strip is mapped, store settings */ - aki.ob= ANIM_nla_mapping_get(ac, ale); + aki.adt= ANIM_nla_mapping_get(ac, ale); if (ac->datatype == ANIMCONT_DOPESHEET) aki.ads= (bDopeSheet *)ac->data; @@ -985,7 +985,7 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar) int filter; View2D *v2d= &ar->v2d; - Object *nob= NULL; + AnimData *adt= NULL; gla2DDrawInfo *di; rcti scr_rct; @@ -1016,18 +1016,18 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar) /* if in NLA there's a strip active, map the view */ if (ac->datatype == ANIMCONT_ACTION) { - nob= ANIM_nla_mapping_get(ac, NULL); + adt= ANIM_nla_mapping_get(ac, NULL); - if (nob) - ANIM_nla_mapping_draw(di, nob, 0); + if (adt) + ANIM_nla_mapping_draw(di, adt, 0); /* start and end of action itself */ calc_action_range(ac->data, &sta, &end, 0); gla2DDrawTranslatePt(di, sta, 0.0f, &act_start, &dummy); gla2DDrawTranslatePt(di, end, 0.0f, &act_end, &dummy); - if (nob) - ANIM_nla_mapping_draw(di, nob, 1); + if (adt) + ANIM_nla_mapping_draw(di, adt, 1); } /* build list of channels to draw */ @@ -1191,10 +1191,10 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar) /* check if anything to show for this channel */ if (ale->datatype != ALE_NONE) { ActKeysInc *aki= init_aki_data(ac, ale); - nob= ANIM_nla_mapping_get(ac, ale); + adt= ANIM_nla_mapping_get(ac, ale); - if (nob) - ANIM_nla_mapping_draw(di, nob, 0); + if (adt) + ANIM_nla_mapping_draw(di, adt, 0); /* draw 'keyframes' for each specific datatype */ switch (ale->datatype) { @@ -1218,8 +1218,8 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar) break; } - if (nob) - ANIM_nla_mapping_draw(di, nob, 1); + if (adt) + ANIM_nla_mapping_draw(di, adt, 1); } } diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index deaa6597bd2..272ef3222ce 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -67,6 +67,7 @@ #include "BKE_fcurve.h" #include "BKE_key.h" #include "BKE_material.h" +#include "BKE_nla.h" #include "BKE_object.h" #include "BKE_context.h" #include "BKE_report.h" @@ -112,16 +113,16 @@ static void get_keyframe_extents (bAnimContext *ac, float *min, float *max) if (anim_data.first) { /* go through channels, finding max extents */ for (ale= anim_data.first; ale; ale= ale->next) { - Object *nob= ANIM_nla_mapping_get(ac, ale); + AnimData *adt= ANIM_nla_mapping_get(ac, ale); FCurve *fcu= (FCurve *)ale->key_data; float tmin, tmax; /* get range and apply necessary scaling before */ calc_fcurve_range(fcu, &tmin, &tmax); - if (nob) { - tmin= get_action_frame_inv(nob, tmin); - tmax= get_action_frame_inv(nob, tmax); + if (adt) { + tmin= BKE_nla_tweakedit_remap(adt, tmin, 1); + tmax= BKE_nla_tweakedit_remap(adt, tmax, 1); } /* try to set cur using these values, if they're more extreme than previously set values */ @@ -400,14 +401,14 @@ static void insert_action_keys(bAnimContext *ac, short mode) /* insert keyframes */ for (ale= anim_data.first; ale; ale= ale->next) { - //Object *nob= ANIM_nla_mapping_get(ac, ale); + AnimData *adt= ANIM_nla_mapping_get(ac, ale); FCurve *fcu= (FCurve *)ale->key_data; /* adjust current frame for NLA-scaling */ - //if (nob) - // cfra= get_action_frame(nob, CFRA); - //else - // cfra= (float)CFRA; + if (adt) + cfra= BKE_nla_tweakedit_remap(adt, (float)CFRA, 1); + else + cfra= (float)CFRA; /* if there's an id */ if (ale->id) @@ -1054,8 +1055,17 @@ static int actkeys_framejump_exec(bContext *C, wmOperator *op) filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVESONLY); ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - for (ale= anim_data.first; ale; ale= ale->next) - ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, bezt_calc_average, NULL); + for (ale= anim_data.first; ale; ale= ale->next) { + AnimData *adt= ANIM_nla_mapping_get(&ac, ale); + + if (adt) { + ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1); + ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, bezt_calc_average, NULL); + ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1); + } + else + ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, bezt_calc_average, NULL); + } BLI_freelistN(&anim_data); @@ -1125,12 +1135,12 @@ static void snap_action_keys(bAnimContext *ac, short mode) /* snap keyframes */ for (ale= anim_data.first; ale; ale= ale->next) { - Object *nob= ANIM_nla_mapping_get(ac, ale); + AnimData *adt= ANIM_nla_mapping_get(ac, ale); - if (nob) { - ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 0, 1); + if (adt) { + ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1); ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, edit_cb, calchandles_fcurve); - ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 1, 1); + ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1); } //else if (ale->type == ACTTYPE_GPLAYER) // snap_gplayer_frames(ale->data, mode); @@ -1241,12 +1251,12 @@ static void mirror_action_keys(bAnimContext *ac, short mode) /* mirror keyframes */ for (ale= anim_data.first; ale; ale= ale->next) { - Object *nob= ANIM_nla_mapping_get(ac, ale); + AnimData *adt= ANIM_nla_mapping_get(ac, ale); - if (nob) { - ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 0, 1); + if (adt) { + ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1); ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, edit_cb, calchandles_fcurve); - ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 1, 1); + ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1); } //else if (ale->type == ACTTYPE_GPLAYER) // snap_gplayer_frames(ale->data, mode); diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c index 4cb39712f84..3583d16fd8c 100644 --- a/source/blender/editors/space_action/action_select.c +++ b/source/blender/editors/space_action/action_select.c @@ -64,6 +64,7 @@ #include "BKE_fcurve.h" #include "BKE_key.h" #include "BKE_material.h" +#include "BKE_nla.h" #include "BKE_object.h" #include "BKE_context.h" #include "BKE_utildefines.h" @@ -245,7 +246,7 @@ static void borderselect_action (bAnimContext *ac, rcti rect, short mode, short /* loop over data, doing border select */ for (ale= anim_data.first; ale; ale= ale->next) { - Object *nob= ANIM_nla_mapping_get(ac, ale); + AnimData *adt= ANIM_nla_mapping_get(ac, ale); /* get new vertical minimum extent of channel */ ymin= ymax - ACHANNEL_STEP; @@ -253,9 +254,9 @@ static void borderselect_action (bAnimContext *ac, rcti rect, short mode, short /* set horizontal range (if applicable) */ if (ELEM(mode, ACTKEYS_BORDERSEL_FRAMERANGE, ACTKEYS_BORDERSEL_ALLKEYS)) { /* if channel is mapped in NLA, apply correction */ - if (nob) { - bed.f1= get_action_frame(nob, rectf.xmin); - bed.f2= get_action_frame(nob, rectf.xmax); + if (adt) { + bed.f1= BKE_nla_tweakedit_remap(adt, rectf.xmin, 0); + bed.f2= BKE_nla_tweakedit_remap(adt, rectf.xmax, 0); } else { bed.f1= rectf.xmin; @@ -413,12 +414,12 @@ static void markers_selectkeys_between (bAnimContext *ac) /* select keys in-between */ for (ale= anim_data.first; ale; ale= ale->next) { - Object *nob= ANIM_nla_mapping_get(ac, ale); + AnimData *adt= ANIM_nla_mapping_get(ac, ale); - if (nob) { - ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 0, 1); + if (adt) { + ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1); ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL); - ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 1, 1); + ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1); } else { ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL); @@ -495,15 +496,15 @@ static void columnselect_action_keys (bAnimContext *ac, short mode) ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); for (ale= anim_data.first; ale; ale= ale->next) { - Object *nob= ANIM_nla_mapping_get(ac, ale); + AnimData *adt= ANIM_nla_mapping_get(ac, ale); /* loop over cfraelems (stored in the BeztEditData->list) * - we need to do this here, as we can apply fewer NLA-mapping conversions */ for (ce= bed.list.first; ce; ce= ce->next) { /* set frame for validation callback to refer to */ - if (nob) - bed.f1= get_action_frame(nob, ce->cfra); + if (adt) + bed.f1= BKE_nla_tweakedit_remap(adt, ce->cfra, 0); else bed.f1= ce->cfra; @@ -658,12 +659,12 @@ static void actkeys_mselect_leftright (bAnimContext *ac, short leftright, short /* select keys on the side where most data occurs */ for (ale= anim_data.first; ale; ale= ale->next) { - Object *nob= ANIM_nla_mapping_get(ac, ale); + AnimData *adt= ANIM_nla_mapping_get(ac, ale); - if (nob) { - ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 0, 1); + if (adt) { + ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1); ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL); - ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 1, 1); + ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1); } //else if (ale->type == ANIMTYPE_GPLAYER) // borderselect_gplayer_frames(ale->data, min, max, SELECT_ADD); @@ -702,11 +703,11 @@ static void actkeys_mselect_column(bAnimContext *ac, short select_mode, float se ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); for (ale= anim_data.first; ale; ale= ale->next) { - Object *nob= ANIM_nla_mapping_get(ac, ale); + AnimData *adt= ANIM_nla_mapping_get(ac, ale); /* set frame for validation callback to refer to */ - if (nob) - bed.f1= get_action_frame(nob, selx); + if (adt) + bed.f1= BKE_nla_tweakedit_remap(adt, selx, 0); else bed.f1= selx; @@ -771,15 +772,15 @@ static void mouse_action_keys (bAnimContext *ac, int mval[2], short select_mode, } else { /* found match - must return here... */ - Object *nob= ANIM_nla_mapping_get(ac, ale); + AnimData *adt= ANIM_nla_mapping_get(ac, ale); ActKeysInc *aki= init_aki_data(ac, ale); ActKeyColumn *ak; float xmin, xmax; /* apply NLA-scaling correction? */ - if (nob) { - xmin= get_action_frame(nob, rectf.xmin); - xmax= get_action_frame(nob, rectf.xmax); + if (adt) { + xmin= BKE_nla_tweakedit_remap(adt, rectf.xmin, 0); + xmax= BKE_nla_tweakedit_remap(adt, rectf.xmax, 0); } else { xmin= rectf.xmin; diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c index acf712d0147..d9e12afc947 100644 --- a/source/blender/editors/space_graph/graph_draw.c +++ b/source/blender/editors/space_graph/graph_draw.c @@ -836,11 +836,11 @@ void graph_draw_curves (bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGri for (ale=anim_data.first; ale; ale=ale->next) { FCurve *fcu= (FCurve *)ale->key_data; FModifier *fcm= fcurve_find_active_modifier(fcu); - //Object *nob= ANIM_nla_mapping_get(ac, ale); + AnimData *adt= ANIM_nla_mapping_get(ac, ale); /* map keyframes for drawing if scaled F-Curve */ - //if (nob) - // ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 0, 0); + if (adt) + ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0); /* draw curve: * - curve line may be result of one or more destructive modifiers or just the raw data, @@ -918,8 +918,8 @@ void graph_draw_curves (bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGri } /* undo mapping of keyframes for drawing if scaled F-Curve */ - //if (nob) - // ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 1, 0); + if (adt) + ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 0); } /* free list of curves */ diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index 8903d95b288..a1888e252d2 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -67,6 +67,7 @@ #include "BKE_fcurve.h" #include "BKE_key.h" #include "BKE_material.h" +#include "BKE_nla.h" #include "BKE_object.h" #include "BKE_context.h" #include "BKE_report.h" @@ -114,16 +115,16 @@ static void get_graph_keyframe_extents (bAnimContext *ac, float *xmin, float *xm if (anim_data.first) { /* go through channels, finding max extents */ for (ale= anim_data.first; ale; ale= ale->next) { - Object *nob= NULL; //ANIM_nla_mapping_get(ac, ale); + AnimData *adt= ANIM_nla_mapping_get(ac, ale); FCurve *fcu= (FCurve *)ale->key_data; float txmin, txmax, tymin, tymax; /* get range and apply necessary scaling before */ calc_fcurve_bounds(fcu, &txmin, &txmax, &tymin, &tymax); - if (nob) { - txmin= get_action_frame_inv(nob, txmin); - txmax= get_action_frame_inv(nob, txmax); + if (adt) { + txmin= BKE_nla_tweakedit_remap(adt, txmin, 1); + txmax= BKE_nla_tweakedit_remap(adt, txmax, 1); } /* try to set cur using these values, if they're more extreme than previously set values */ @@ -271,6 +272,7 @@ static void create_ghost_curves (bAnimContext *ac, int start, int end) for (ale= anim_data.first; ale; ale= ale->next) { FCurve *fcu= (FCurve *)ale->key_data; FCurve *gcu= MEM_callocN(sizeof(FCurve), "Ghost FCurve"); + AnimData *adt= ANIM_nla_mapping_get(ac, ale); ChannelDriver *driver= fcu->driver; FPoint *fpt; int cfra; @@ -286,8 +288,10 @@ static void create_ghost_curves (bAnimContext *ac, int start, int end) /* use the sampling callback at 1-frame intervals from start to end frames */ for (cfra= start; cfra <= end; cfra++, fpt++) { - fpt->vec[0]= (float)cfra; - fpt->vec[1]= fcurve_samplingcb_evalcurve(fcu, NULL, (float)cfra); + float cfrae= BKE_nla_tweakedit_remap(adt, cfra, 1); + + fpt->vec[0]= cfrae; + fpt->vec[1]= fcurve_samplingcb_evalcurve(fcu, NULL, cfrae); } /* set color of ghost curve @@ -403,6 +407,7 @@ static int graphkeys_click_insert_exec (bContext *C, wmOperator *op) { bAnimContext ac; bAnimListElem *ale; + AnimData *adt; float frame, val; /* get animation context */ @@ -420,6 +425,10 @@ static int graphkeys_click_insert_exec (bContext *C, wmOperator *op) frame= RNA_float_get(op->ptr, "frame"); val= RNA_float_get(op->ptr, "value"); + /* apply inverse NLA-mapping to frame to get correct time in un-scaled action */ + adt= ANIM_nla_mapping_get(&ac, ale); + frame= BKE_nla_tweakedit_remap(adt, frame, 1); + /* insert keyframe on the specified frame + value */ insert_vert_fcurve((FCurve *)ale->data, frame, val, 0); @@ -1336,8 +1345,18 @@ static int graphkeys_framejump_exec(bContext *C, wmOperator *op) filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE| ANIMFILTER_CURVESONLY); ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - for (ale= anim_data.first; ale; ale= ale->next) - ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, bezt_calc_average, NULL); + for (ale= anim_data.first; ale; ale= ale->next) { + AnimData *adt= ANIM_nla_mapping_get(&ac, ale); + + if (adt) { + ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1); + ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, bezt_calc_average, NULL); + ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1); + } + else + ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, bezt_calc_average, NULL); + + } BLI_freelistN(&anim_data); @@ -1405,12 +1424,12 @@ static void snap_graph_keys(bAnimContext *ac, short mode) /* snap keyframes */ for (ale= anim_data.first; ale; ale= ale->next) { - Object *nob= ANIM_nla_mapping_get(ac, ale); + AnimData *adt= ANIM_nla_mapping_get(ac, ale); - if (nob) { - ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 0, 1); + if (adt) { + ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1); ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, edit_cb, calchandles_fcurve); - ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 1, 1); + ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1); } else ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, edit_cb, calchandles_fcurve); @@ -1516,12 +1535,12 @@ static void mirror_graph_keys(bAnimContext *ac, short mode) /* mirror keyframes */ for (ale= anim_data.first; ale; ale= ale->next) { - Object *nob= ANIM_nla_mapping_get(ac, ale); + AnimData *adt= ANIM_nla_mapping_get(ac, ale); - if (nob) { - ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 0, 1); + if (adt) { + ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1); ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, edit_cb, calchandles_fcurve); - ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 1, 1); + ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1); } else ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, edit_cb, calchandles_fcurve); diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c index 632ce30863d..4451cfae227 100644 --- a/source/blender/editors/space_graph/graph_select.c +++ b/source/blender/editors/space_graph/graph_select.c @@ -63,6 +63,7 @@ #include "BKE_fcurve.h" #include "BKE_key.h" #include "BKE_material.h" +#include "BKE_nla.h" #include "BKE_object.h" #include "BKE_context.h" #include "BKE_utildefines.h" @@ -231,14 +232,14 @@ static void borderselect_graphkeys (bAnimContext *ac, rcti rect, short mode, sho /* loop over data, doing border select */ for (ale= anim_data.first; ale; ale= ale->next) { - Object *nob= ANIM_nla_mapping_get(ac, ale); + AnimData *adt= ANIM_nla_mapping_get(ac, ale); /* set horizontal range (if applicable) */ if (mode != BEZT_OK_VALUERANGE) { /* if channel is mapped in NLA, apply correction */ - if (nob) { - bed.f1= get_action_frame(nob, rectf.xmin); - bed.f2= get_action_frame(nob, rectf.xmax); + if (adt) { + bed.f1= BKE_nla_tweakedit_remap(adt, rectf.xmin, 0); + bed.f2= BKE_nla_tweakedit_remap(adt, rectf.xmax, 0); } else { bed.f1= rectf.xmin; @@ -379,12 +380,12 @@ static void markers_selectkeys_between (bAnimContext *ac) /* select keys in-between */ for (ale= anim_data.first; ale; ale= ale->next) { - Object *nob= ANIM_nla_mapping_get(ac, ale); + AnimData *adt= ANIM_nla_mapping_get(ac, ale); - if (nob) { - ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 0, 1); + if (adt) { + ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1); ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL); - ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 1, 1); + ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1); } else { ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL); @@ -450,15 +451,15 @@ static void columnselect_graph_keys (bAnimContext *ac, short mode) ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); for (ale= anim_data.first; ale; ale= ale->next) { - Object *nob= ANIM_nla_mapping_get(ac, ale); + AnimData *adt= ANIM_nla_mapping_get(ac, ale); /* loop over cfraelems (stored in the BeztEditData->list) * - we need to do this here, as we can apply fewer NLA-mapping conversions */ for (ce= bed.list.first; ce; ce= ce->next) { /* set frame for validation callback to refer to */ - if (nob) - bed.f1= get_action_frame(nob, ce->cfra); + if (ale) + bed.f1= BKE_nla_tweakedit_remap(adt, ce->cfra, 0); else bed.f1= ce->cfra; @@ -566,11 +567,16 @@ static short findnearest_fcurve_vert (bAnimContext *ac, int mval[2], FCurve **fc for (ale= anim_data.first; ale; ale= ale->next) { FCurve *fcu= (FCurve *)ale->key_data; + AnimData *adt= ANIM_nla_mapping_get(ac, ale); /* try to progressively get closer to the right point... */ if (fcu->bezt) { BezTriple *bezt1=fcu->bezt, *prevbezt=NULL; + /* apply NLA mapping to all the keyframes */ + if (adt) + ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1); + for (i=0; i < fcu->totvert; i++, prevbezt=bezt1, bezt1++) { /* convert beztriple points to screen-space */ UI_view2d_to_region_no_clip(v2d, bezt1->vec[0][0], bezt1->vec[0][1], &sco[0][0], &sco[0][1]); @@ -624,6 +630,10 @@ static short findnearest_fcurve_vert (bAnimContext *ac, int mval[2], FCurve **fc } } } + + /* un-apply NLA mapping from all the keyframes */ + if (adt) + ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1); } } @@ -767,12 +777,12 @@ static void graphkeys_mselect_leftright (bAnimContext *ac, short leftright, shor /* select keys on the side where most data occurs */ for (ale= anim_data.first; ale; ale= ale->next) { - Object *nob= ANIM_nla_mapping_get(ac, ale); + AnimData *adt= ANIM_nla_mapping_get(ac, ale); - if (nob) { - ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 0, 1); + if (adt) { + ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1); ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL); - ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 1, 1); + ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1); } else ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL); @@ -827,11 +837,11 @@ static void graphkeys_mselect_column (bAnimContext *ac, int mval[2], short selec ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); for (ale= anim_data.first; ale; ale= ale->next) { - Object *nob= ANIM_nla_mapping_get(ac, ale); + AnimData *adt= ANIM_nla_mapping_get(ac, ale); /* set frame for validation callback to refer to */ - if (nob) - bed.f1= get_action_frame(nob, selx); + if (adt) + bed.f1= BKE_nla_tweakedit_remap(adt, selx, 0); else bed.f1= selx; diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index fa93d2a143d..f115bb9a068 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -45,6 +45,7 @@ #include "MEM_guardedalloc.h" +#include "DNA_anim_types.h" #include "DNA_armature_types.h" #include "DNA_action_types.h" /* for some special action-editor settings */ #include "DNA_constraint_types.h" @@ -76,9 +77,9 @@ //#include "BIF_editmesh.h" //#include "BIF_editsima.h" //#include "BIF_editparticle.h" -//#include "BIF_editaction.h" -#include "BKE_action.h" /* get_action_frame */ +#include "BKE_action.h" +#include "BKE_nla.h" //#include "BKE_bad_level_calls.h"/* popmenu and error */ #include "BKE_bmesh.h" #include "BKE_context.h" @@ -89,7 +90,6 @@ #include "BKE_utildefines.h" #include "BKE_context.h" -//#include "BSE_editaction_types.h" //#include "BSE_view.h" #include "ED_image.h" @@ -4354,7 +4354,7 @@ static short getAnimEdit_DrawTime(TransInfo *t) /* This function is used by Animation Editor specific transform functions to do * the Snap Keyframe to Nearest Frame/Marker */ -static void doAnimEdit_SnapFrame(TransInfo *t, TransData *td, Object *ob, short autosnap) +static void doAnimEdit_SnapFrame(TransInfo *t, TransData *td, AnimData *adt, short autosnap) { /* snap key to nearest frame? */ if (autosnap == SACTSNAP_FRAME) { @@ -4364,8 +4364,8 @@ static void doAnimEdit_SnapFrame(TransInfo *t, TransData *td, Object *ob, short double val; /* convert frame to nla-action time (if needed) */ - if (ob) - val= get_action_frame_inv(ob, *(td->val)); + if (adt) + val= BKE_nla_tweakedit_remap(adt, *(td->val), 1); else val= *(td->val); @@ -4376,8 +4376,8 @@ static void doAnimEdit_SnapFrame(TransInfo *t, TransData *td, Object *ob, short val= (float)( floor(val+0.5f) ); /* convert frame out of nla-action time */ - if (ob) - *(td->val)= get_action_frame(ob, val); + if (adt) + *(td->val)= BKE_nla_tweakedit_remap(adt, val, 0); else *(td->val)= val; } @@ -4386,8 +4386,8 @@ static void doAnimEdit_SnapFrame(TransInfo *t, TransData *td, Object *ob, short float val; /* convert frame to nla-action time (if needed) */ - if (ob) - val= get_action_frame_inv(ob, *(td->val)); + if (adt) + val= BKE_nla_tweakedit_remap(adt, *(td->val), 1); else val= *(td->val); @@ -4396,8 +4396,8 @@ static void doAnimEdit_SnapFrame(TransInfo *t, TransData *td, Object *ob, short val= (float)ED_markers_find_nearest_marker_time(&t->scene->markers, val); /* convert frame out of nla-action time */ - if (ob) - *(td->val)= get_action_frame(ob, val); + if (adt) + *(td->val)= BKE_nla_tweakedit_remap(adt, val, 0); else *(td->val)= val; } @@ -4473,10 +4473,10 @@ static void applyTimeTranslate(TransInfo *t, float sval) /* it is assumed that td->ob is a pointer to the object, * whose active action is where this keyframe comes from */ - Object *ob= td->ob; + AnimData *adt= td->extra; - /* check if any need to apply nla-scaling */ - if (ob) { + /* check if any need to apply nla-mapping */ + if (adt) { deltax = t->values[0]; if (autosnap == SACTSNAP_STEP) { @@ -4486,9 +4486,9 @@ static void applyTimeTranslate(TransInfo *t, float sval) deltax= (float)( floor(deltax + 0.5f) ); } - val = get_action_frame_inv(ob, td->ival); + val = BKE_nla_tweakedit_remap(adt, td->ival, 1); val += deltax; - *(td->val) = get_action_frame(ob, val); + *(td->val) = BKE_nla_tweakedit_remap(adt, val, 0); } else { deltax = val = t->values[0]; @@ -4504,7 +4504,7 @@ static void applyTimeTranslate(TransInfo *t, float sval) } /* apply nearest snapping */ - doAnimEdit_SnapFrame(t, td, ob, autosnap); + doAnimEdit_SnapFrame(t, td, adt, autosnap); } } @@ -4604,15 +4604,15 @@ static void applyTimeSlide(TransInfo *t, float sval) /* it doesn't matter whether we apply to t->data or t->data2d, but t->data2d is more convenient */ for (i = 0 ; i < t->total; i++, td++) { - /* it is assumed that td->ob is a pointer to the object, + /* it is assumed that td->extra is a pointer to the AnimData, * whose active action is where this keyframe comes from */ - Object *ob= td->ob; + AnimData *adt= td->extra; float cval = t->values[0]; - /* apply scaling to necessary values */ - if (ob) - cval= get_action_frame(ob, cval); + /* apply NLA-mapping to necessary values */ + if (adt) + cval= BKE_nla_tweakedit_remap(adt, cval, 0); /* only apply to data if in range */ if ((sval > minx) && (sval < maxx)) { @@ -4707,10 +4707,10 @@ static void applyTimeScale(TransInfo *t) { for (i = 0 ; i < t->total; i++, td++) { - /* it is assumed that td->ob is a pointer to the object, + /* it is assumed that td->extra is a pointer to the AnimData, * whose active action is where this keyframe comes from */ - Object *ob= td->ob; + AnimData *adt= td->extra; float startx= CFRA; float fac= t->values[0]; @@ -4721,9 +4721,9 @@ static void applyTimeScale(TransInfo *t) { fac= (float)( floor(fac + 0.5f) ); } - /* check if any need to apply nla-scaling */ - if (ob) - startx= get_action_frame(ob, startx); + /* check if any need to apply nla-mapping */ + if (adt) + startx= BKE_nla_tweakedit_remap(adt, startx, 0); /* now, calculate the new value */ *(td->val) = td->ival - startx; @@ -4731,7 +4731,7 @@ static void applyTimeScale(TransInfo *t) { *(td->val) += startx; /* apply nearest snapping */ - doAnimEdit_SnapFrame(t, td, ob, autosnap); + doAnimEdit_SnapFrame(t, td, adt, autosnap); } } diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index cb210a37bf4..fc5a6b85de4 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -90,6 +90,7 @@ #include "BKE_mball.h" #include "BKE_mesh.h" #include "BKE_modifier.h" +#include "BKE_nla.h" #include "BKE_object.h" #include "BKE_particle.h" #include "BKE_sequence.h" @@ -2857,12 +2858,12 @@ static void posttrans_action_clean (bAnimContext *ac, bAction *act) * - all keyframes are converted in/out of global time */ for (ale= anim_data.first; ale; ale= ale->next) { - Object *nob= ANIM_nla_mapping_get(ac, ale); + AnimData *adt= ANIM_nla_mapping_get(ac, ale); - if (nob) { - //ANIM_nla_mapping_apply_ipocurve(nob, ale->key_data, 0, 1); + if (adt) { + ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1); posttrans_fcurve_clean(ale->key_data); - //ANIM_nla_mapping_apply_ipocurve(nob, ale->key_data, 1, 1); + ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1); } else posttrans_fcurve_clean(ale->key_data); @@ -2920,17 +2921,16 @@ static int count_gplayer_frames(bGPDlayer *gpl, char side, float cfra) } /* This function assigns the information to transdata */ -static void TimeToTransData(TransData *td, float *time, Object *ob) +static void TimeToTransData(TransData *td, float *time, AnimData *adt) { /* memory is calloc'ed, so that should zero everything nicely for us */ td->val = time; td->ival = *(time); - /* store the Object where this keyframe exists as a keyframe of the - * active action as td->ob. Usually, this member is only used for constraints - * drawing + /* store the AnimData where this keyframe exists as a keyframe of the + * active action as td->extra. */ - td->ob= ob; + td->extra= adt; } /* This function advances the address to which td points to, so it must return @@ -2940,7 +2940,7 @@ static void TimeToTransData(TransData *td, float *time, Object *ob) * The 'side' argument is needed for the extend mode. 'B' = both sides, 'R'/'L' mean only data * on the named side are used. */ -static TransData *FCurveToTransData(TransData *td, FCurve *fcu, Object *ob, char side, float cfra) +static TransData *FCurveToTransData(TransData *td, FCurve *fcu, AnimData *adt, char side, float cfra) { BezTriple *bezt; int i; @@ -2954,13 +2954,13 @@ static TransData *FCurveToTransData(TransData *td, FCurve *fcu, Object *ob, char /* only add if on the right 'side' of the current frame */ if (FrameOnMouseSide(side, bezt->vec[1][0], cfra)) { /* each control point needs to be added separetely */ - TimeToTransData(td, bezt->vec[0], ob); + TimeToTransData(td, bezt->vec[0], adt); td++; - TimeToTransData(td, bezt->vec[1], ob); + TimeToTransData(td, bezt->vec[1], adt); td++; - TimeToTransData(td, bezt->vec[2], ob); + TimeToTransData(td, bezt->vec[2], adt); td++; } } @@ -3068,13 +3068,13 @@ static void createTransActionData(bContext *C, TransInfo *t) /* loop 1: fully select ipo-keys and count how many BezTriples are selected */ for (ale= anim_data.first; ale; ale= ale->next) { - Object *nob= ANIM_nla_mapping_get(&ac, ale); + AnimData *adt= ANIM_nla_mapping_get(&ac, ale); /* convert current-frame to action-time (slightly less accurate, espcially under * higher scaling ratios, but is faster than converting all points) */ - if (nob) - cfra = get_action_frame(nob, (float)CFRA); + if (adt) + cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, 0); else cfra = (float)CFRA; @@ -3121,18 +3121,18 @@ static void createTransActionData(bContext *C, TransInfo *t) // tfd += i; //} //else { - Object *nob= ANIM_nla_mapping_get(&ac, ale); + AnimData *adt= ANIM_nla_mapping_get(&ac, ale); FCurve *fcu= (FCurve *)ale->key_data; /* convert current-frame to action-time (slightly less accurate, espcially under * higher scaling ratios, but is faster than converting all points) */ - if (nob) - cfra = get_action_frame(nob, (float)CFRA); + if (adt) + cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, 0); else cfra = (float)CFRA; - td= FCurveToTransData(td, fcu, nob, side, cfra); + td= FCurveToTransData(td, fcu, adt, side, cfra); //} } @@ -3164,23 +3164,23 @@ static void createTransActionData(bContext *C, TransInfo *t) /* Helper function for createTransGraphEditData, which is reponsible for associating * source data with transform data */ -static void bezt_to_transdata (TransData *td, TransData2D *td2d, Object *nob, float *loc, float *cent, short selected, short ishandle, short intvals) +static void bezt_to_transdata (TransData *td, TransData2D *td2d, AnimData *adt, float *loc, float *cent, short selected, short ishandle, short intvals) { /* New location from td gets dumped onto the old-location of td2d, which then * gets copied to the actual data at td2d->loc2d (bezt->vec[n]) * - * Due to NLA scaling, we apply NLA scaling to some of the verts here, - * and then that scaling will be undone after transform is done. + * Due to NLA mapping, we apply NLA mapping to some of the verts here, + * and then that mapping will be undone after transform is done. */ - if (nob) { - td2d->loc[0] = get_action_frame_inv(nob, loc[0]); + if (adt) { + td2d->loc[0] = BKE_nla_tweakedit_remap(adt, loc[0], 0); td2d->loc[1] = loc[1]; td2d->loc[2] = 0.0f; td2d->loc2d = loc; td->loc = td2d->loc; - td->center[0] = get_action_frame_inv(nob, cent[0]); + td->center[0] = BKE_nla_tweakedit_remap(adt, cent[0], 0); td->center[1] = cent[1]; td->center[2] = 0.0f; @@ -3201,6 +3201,9 @@ static void bezt_to_transdata (TransData *td, TransData2D *td2d, Object *nob, fl td->axismtx[2][2] = 1.0f; td->ext= NULL; td->tdi= NULL; td->val= NULL; + + /* store AnimData info in td->extra, for applying mapping when flushing */ + td->extra= adt; if (selected) { td->flag |= TD_SELECTED; @@ -3261,14 +3264,14 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) /* loop 1: count how many BezTriples (specifically their verts) are selected (or should be edited) */ for (ale= anim_data.first; ale; ale= ale->next) { - Object *nob= NULL; //ANIM_nla_mapping_get(&ac, ale); // XXX we don't handle NLA mapping for now here... + AnimData *adt= ANIM_nla_mapping_get(&ac, ale); FCurve *fcu= (FCurve *)ale->key_data; /* convert current-frame to action-time (slightly less accurate, espcially under * higher scaling ratios, but is faster than converting all points) */ - if (nob) - cfra = get_action_frame(nob, (float)CFRA); + if (adt) + cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, 1); else cfra = (float)CFRA; @@ -3318,13 +3321,19 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) td2d= t->data2d; /* loop 2: build transdata arrays */ - cfra = (float)CFRA; - for (ale= anim_data.first; ale; ale= ale->next) { - Object *nob= NULL; //ANIM_nla_mapping_get(&ac, ale); // XXX we don't handle NLA mapping here yet + AnimData *adt= ANIM_nla_mapping_get(&ac, ale); FCurve *fcu= (FCurve *)ale->key_data; short intvals= (fcu->flag & FCURVE_INT_VALUES); + /* convert current-frame to action-time (slightly less accurate, espcially under + * higher scaling ratios, but is faster than converting all points) + */ + if (adt) + cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, 1); + else + cfra = (float)CFRA; + /* only include BezTriples whose 'keyframe' occurs on the same side of the current frame as mouse (if applicable) */ bezt= fcu->bezt; prevbezt= NULL; @@ -3338,7 +3347,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) if ( (!prevbezt && (bezt->ipo==BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo==BEZT_IPO_BEZ)) ) { if (bezt->f1 & SELECT) { hdata = initTransDataCurveHandes(td, bezt); - bezt_to_transdata(td++, td2d++, nob, bezt->vec[0], bezt->vec[1], 1, 1, intvals); + bezt_to_transdata(td++, td2d++, adt, bezt->vec[0], bezt->vec[1], 1, 1, intvals); } else h1= 0; @@ -3347,7 +3356,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) if (bezt->f3 & SELECT) { if (hdata==NULL) hdata = initTransDataCurveHandes(td, bezt); - bezt_to_transdata(td++, td2d++, nob, bezt->vec[2], bezt->vec[1], 1, 1, intvals); + bezt_to_transdata(td++, td2d++, adt, bezt->vec[2], bezt->vec[1], 1, 1, intvals); } else h2= 0; @@ -3363,7 +3372,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) hdata = initTransDataCurveHandes(td, bezt); } - bezt_to_transdata(td++, td2d++, nob, bezt->vec[1], bezt->vec[1], 1, 0, intvals); + bezt_to_transdata(td++, td2d++, adt, bezt->vec[1], bezt->vec[1], 1, 0, intvals); } /* special hack (must be done after initTransDataCurveHandes(), as that stores handle settings to restore...): @@ -3587,6 +3596,8 @@ void flushTransGraphData(TransInfo *t) /* flush to 2d vector from internally used 3d vector */ for (a=0, td= t->data, td2d=t->data2d; atotal; a++, td++, td2d++) { + AnimData *adt= (AnimData *)td->extra; /* pointers to relevant AnimData blocks are stored in the td->extra pointers */ + /* handle snapping for time values * - we should still be in NLA-mapping timespace * - only apply to keyframes (but never to handles) @@ -3604,9 +3615,9 @@ void flushTransGraphData(TransInfo *t) } /* we need to unapply the nla-scaling from the time in some situations */ - //if (NLA_IPO_SCALED) - // td2d->loc2d[0]= get_action_frame(OBACT, td2d->loc[0]); - //else + if (adt) + td2d->loc2d[0]= BKE_nla_tweakedit_remap(adt, td2d->loc[0], 0); + else td2d->loc2d[0]= td2d->loc[0]; /* if int-values only, truncate to integers */ @@ -4584,16 +4595,16 @@ void special_aftertrans_update(TransInfo *t) /* these should all be ipo-blocks */ for (ale= anim_data.first; ale; ale= ale->next) { - Object *nob= ANIM_nla_mapping_get(&ac, ale); + AnimData *adt= ANIM_nla_mapping_get(&ac, ale); FCurve *fcu= (FCurve *)ale->key_data; if ( (saction->flag & SACTION_NOTRANSKEYCULL)==0 && ((cancelled == 0) || (duplicate)) ) { - if (nob) { - ANIM_nla_mapping_apply_fcurve(nob, fcu, 0, 1); + if (adt) { + ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 1); posttrans_fcurve_clean(fcu); - ANIM_nla_mapping_apply_fcurve(nob, fcu, 1, 1); + ANIM_nla_mapping_apply_fcurve(adt, fcu, 1, 1); } else posttrans_fcurve_clean(fcu); @@ -4695,16 +4706,16 @@ void special_aftertrans_update(TransInfo *t) /* these should all be ipo-blocks */ for (ale= anim_data.first; ale; ale= ale->next) { - Object *nob= ANIM_nla_mapping_get(&ac, ale); + AnimData *adt= ANIM_nla_mapping_get(&ac, ale); FCurve *fcu= (FCurve *)ale->key_data; if ( (sipo->flag & SIPO_NOTRANSKEYCULL)==0 && ((cancelled == 0) || (duplicate)) ) { - if (nob) { - ANIM_nla_mapping_apply_fcurve(nob, fcu, 0, 1); + if (adt) { + ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 1); posttrans_fcurve_clean(fcu); - ANIM_nla_mapping_apply_fcurve(nob, fcu, 1, 1); + ANIM_nla_mapping_apply_fcurve(adt, fcu, 1, 1); } else posttrans_fcurve_clean(fcu); diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 4c9592fb27a..a60135107bc 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -272,37 +272,6 @@ void recalcData(TransInfo *t) Scene *scene = t->scene; Base *base; -#if 0 // TRANSFORM_FIX_ME - if (t->spacetype == SPACE_ACTION) { - Object *ob= OBACT; - void *data; - short context; - - /* determine what type of data we are operating on */ - data = get_action_context(&context); - if (data == NULL) return; - - /* always flush data if gpencil context */ - if (context == ACTCONT_GPENCIL) { - flushTransGPactionData(t); - } - - if (G.saction->lock) { - if (context == ACTCONT_ACTION) { - if(ob) { - ob->ctime= -1234567.0f; - if(ob->pose || ob_get_key(ob)) - DAG_object_flush_update(G.scene, ob, OB_RECALC); - else - DAG_object_flush_update(G.scene, ob, OB_RECALC_OB); - } - } - else if (context == ACTCONT_SHAPEKEY) { - DAG_object_flush_update(G.scene, OBACT, OB_RECALC_OB|OB_RECALC_DATA); - } - } - } -#endif if (t->obedit) { } else if(G.f & G_PARTICLEEDIT) { diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h index a784adaf35f..2b089530236 100644 --- a/source/blender/makesdna/DNA_anim_types.h +++ b/source/blender/makesdna/DNA_anim_types.h @@ -1,5 +1,28 @@ -/* Testing code for new animation system in 2.5 - * Copyright 2009, Joshua Leung +/** + * $Id: DNA_anim_types.h 21023 2009-06-20 04:02:49Z aligorith $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung + * All rights reserved. + * + * Contributor(s): Joshua Leung (full recode) + * + * ***** END GPL LICENSE BLOCK ***** */ #ifndef DNA_ANIM_TYPES_H @@ -668,6 +691,8 @@ typedef struct AnimData { /* nla-tracks */ ListBase nla_tracks; + /* active NLA-strip (only set/used during tweaking, so no need to worry about dangling pointers) */ + NlaStrip *actstrip; /* 'drivers' for this ID-block's settings - FCurves, but are completely * separate from those for animation data From 0336c2e7f5df2b104532a04161b3924870567ab3 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Wed, 24 Jun 2009 01:04:01 +0000 Subject: [PATCH 055/114] NLA SoC: Fixing a few cases where the wrong flags got used in last night's commit --- source/blender/editors/space_action/action_edit.c | 2 +- source/blender/editors/space_graph/graph_edit.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index 272ef3222ce..70dbc42fe6e 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -406,7 +406,7 @@ static void insert_action_keys(bAnimContext *ac, short mode) /* adjust current frame for NLA-scaling */ if (adt) - cfra= BKE_nla_tweakedit_remap(adt, (float)CFRA, 1); + cfra= BKE_nla_tweakedit_remap(adt, (float)CFRA, 0); else cfra= (float)CFRA; diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index a1888e252d2..057c3c40ddf 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -288,7 +288,7 @@ static void create_ghost_curves (bAnimContext *ac, int start, int end) /* use the sampling callback at 1-frame intervals from start to end frames */ for (cfra= start; cfra <= end; cfra++, fpt++) { - float cfrae= BKE_nla_tweakedit_remap(adt, cfra, 1); + float cfrae= BKE_nla_tweakedit_remap(adt, cfra, 0); fpt->vec[0]= cfrae; fpt->vec[1]= fcurve_samplingcb_evalcurve(fcu, NULL, cfrae); @@ -427,7 +427,7 @@ static int graphkeys_click_insert_exec (bContext *C, wmOperator *op) /* apply inverse NLA-mapping to frame to get correct time in un-scaled action */ adt= ANIM_nla_mapping_get(&ac, ale); - frame= BKE_nla_tweakedit_remap(adt, frame, 1); + frame= BKE_nla_tweakedit_remap(adt, frame, 0); /* insert keyframe on the specified frame + value */ insert_vert_fcurve((FCurve *)ale->data, frame, val, 0); From 717916c2b9975b08ed35a8224bf17ccb6df3310b Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Wed, 24 Jun 2009 01:41:12 +0000 Subject: [PATCH 056/114] NLA SoC: Fixes for segfaults during NLA Transforms The snapping code was incorrectly assuming that td->extra was always AnimData, but for NLA this is incorrect as it is used for special data used for checking back. --- source/blender/editors/transform/transform.c | 23 ++++++------------- .../editors/transform/transform_conversions.c | 4 ++-- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index f115bb9a068..a417aa46773 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -4470,10 +4470,11 @@ static void applyTimeTranslate(TransInfo *t, float sval) /* it doesn't matter whether we apply to t->data or t->data2d, but t->data2d is more convenient */ for (i = 0 ; i < t->total; i++, td++) { - /* it is assumed that td->ob is a pointer to the object, + /* it is assumed that td->extra is a pointer to the AnimData, * whose active action is where this keyframe comes from + * (this is only valid when not in NLA) */ - AnimData *adt= td->extra; + AnimData *adt= (t->spacetype != SPACE_NLA) ? td->extra : NULL; /* check if any need to apply nla-mapping */ if (adt) { @@ -4606,8 +4607,9 @@ static void applyTimeSlide(TransInfo *t, float sval) for (i = 0 ; i < t->total; i++, td++) { /* it is assumed that td->extra is a pointer to the AnimData, * whose active action is where this keyframe comes from + * (this is only valid when not in NLA) */ - AnimData *adt= td->extra; + AnimData *adt= (t->spacetype != SPACE_NLA) ? td->extra : NULL; float cval = t->values[0]; /* apply NLA-mapping to necessary values */ @@ -4709,8 +4711,9 @@ static void applyTimeScale(TransInfo *t) { for (i = 0 ; i < t->total; i++, td++) { /* it is assumed that td->extra is a pointer to the AnimData, * whose active action is where this keyframe comes from + * (this is only valid when not in NLA) */ - AnimData *adt= td->extra; + AnimData *adt= (t->spacetype != SPACE_NLA) ? td->extra : NULL; float startx= CFRA; float fac= t->values[0]; @@ -4745,18 +4748,6 @@ int TimeScale(TransInfo *t, short mval[2]) sval= t->imval[0]; cval= mval[0]; - // XXX ewww... we need a better factor! -#if 0 // TRANSFORM_FIX_ME - switch (t->spacetype) { - case SPACE_ACTION: - width= ACTWIDTH; - break; - case SPACE_NLA: - width= NLAWIDTH; - break; - } -#endif - /* calculate scaling factor */ startx= sval-(width/2+(t->ar->winx)/2); deltax= cval-(width/2+(t->ar->winx)/2); diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index fc5a6b85de4..1f75384880e 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -3271,7 +3271,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) * higher scaling ratios, but is faster than converting all points) */ if (adt) - cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, 1); + cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, 0); else cfra = (float)CFRA; @@ -3330,7 +3330,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) * higher scaling ratios, but is faster than converting all points) */ if (adt) - cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, 1); + cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, 0); else cfra = (float)CFRA; From e5119ee2c0d5b9510d89364600e08e40a4407f40 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Wed, 24 Jun 2009 10:32:13 +0000 Subject: [PATCH 057/114] NLA SoC: Drawing Tweaks * Transition tracks are now drawn in a different colour (bluish) * Action line now shows keyframe indicators for the action it is representing. These are drawn as small empty diamonds to show that they're not directly editable (and never ever will be) via the NLA Editor. * Action line is also drawn with borders to help differentiate it from the other tracks. * As an experiment, removed the 'TweakMode' buttons from the header. I had originally added this as a way of indicating that this functionality was there (and to allow for keeping track of it), though it seems to have caused far too much confusion and frustration about 'modality' instead. --- source/blender/blenkernel/intern/nla.c | 2 +- source/blender/editors/space_nla/nla_draw.c | 154 +++++++++++++++--- source/blender/editors/space_nla/nla_header.c | 9 - 3 files changed, 130 insertions(+), 35 deletions(-) diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index a5b3b59d310..747113b6531 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -433,7 +433,7 @@ float BKE_nla_tweakedit_remap (AnimData *adt, float cframe, short invert) * and store for (very probable) future usage */ if (adt->actstrip == NULL) { - NlaTrack *nlt= BKE_nlatrack_find_active(adt); + NlaTrack *nlt= BKE_nlatrack_find_active(&adt->nla_tracks); adt->actstrip= BKE_nlastrip_find_active(nlt); } strip= adt->actstrip; diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index 2ac2b557243..5a22da2eb25 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -64,6 +64,7 @@ #include "BKE_utildefines.h" #include "ED_anim_api.h" +#include "ED_keyframes_draw.h" #include "ED_space_api.h" #include "ED_screen.h" @@ -89,33 +90,120 @@ extern void gl_round_box_shade(int mode, float minx, float miny, float maxx, flo /* *********************************************** */ /* Strips */ +/* Keyframe Ghosts ---------------------- */ + +/* helper func - draw keyframe as a frame only */ +static void draw_nla_keyframe_ghost (float x, float y, float xscale, float hsize) +{ + static GLuint displist=0; + + /* initialise empty diamond shape */ + if (displist == 0) { + const float dist= 1.0f; + + displist= glGenLists(1); + glNewList(displist, GL_COMPILE); + + glBegin(GL_LINE_LOOP); + glVertex2f(0.0f, dist); + glVertex2f(dist, 0.0f); + glVertex2f(0.0f, -dist); + glVertex2f(-dist, 0.0f); + glEnd(); + + glEndList(); + } + + /* adjust view transform before starting */ + glTranslatef(x, y, 0.0f); + glScalef(1.0f/xscale*hsize, hsize, 1.0f); + + /* anti-aliased lines for more consistent appearance */ + glEnable(GL_LINE_SMOOTH); + + /* draw! */ + glCallList(displist); + + glDisable(GL_LINE_SMOOTH); + + /* restore view transform */ + glScalef(xscale/hsize, 1.0f/hsize, 1.0); + glTranslatef(-x, -y, 0.0f); +} + +/* draw the keyframes in the specified Action */ +static void nla_action_draw_keyframes (AnimData *adt, View2D *v2d, float y) +{ + ListBase keys = {NULL, NULL}; + ActKeyColumn *ak; + float xscale; + + /* for now, color is hardcoded to be black */ + glColor3f(0.0f, 0.0f, 0.0f); + + /* get a list of the keyframes with NLA-scaling applied */ + action_nlascaled_to_keylist(adt, adt->action, &keys, NULL, NULL); + + /* get View2D scaling factor */ + UI_view2d_getscale(v2d, &xscale, NULL); + + /* just draw each keyframe as a simple dot (regardless of the selection status) */ + for (ak= keys.first; ak; ak= ak->next) + draw_nla_keyframe_ghost(ak->cfra, y, xscale, 3.0f); + + /* free icons */ + BLI_freelistN(&keys); +} + +/* Strips (Proper) ---------------------- */ + static void nla_strip_get_color_inside (AnimData *adt, NlaStrip *strip, float color[3]) { - if ((strip->flag & NLASTRIP_FLAG_ACTIVE) && (adt && (adt->flag & ADT_NLA_EDIT_ON))) { - /* active strip should be drawn green when it is acting as the tweaking strip. - * however, this case should be skipped for when not in EditMode... - */ - // FIXME: hardcoded temp-hack colors - color[0]= 0.3f; - color[1]= 0.95f; - color[2]= 0.1f; - } - else if (strip->flag & NLASTRIP_FLAG_TWEAKUSER) { - /* alert user that this strip is also used by the tweaking track (this is set when going into - * 'editmode' for that strip), since the edits made here may not be what the user anticipated - */ - // FIXME: hardcoded temp-hack colors - color[0]= 0.85f; - color[1]= 0.0f; - color[2]= 0.0f; - } - else if (strip->flag & NLASTRIP_FLAG_SELECT) { - /* selected strip - use theme color for selected */ - UI_GetThemeColor3fv(TH_STRIP_SELECT, color); - } + if (strip->type == NLASTRIP_TYPE_TRANSITION) { + /* Transition Clip */ + if (strip->flag & NLASTRIP_FLAG_SELECT) { + /* selected - use a bright blue color */ + // FIXME: hardcoded temp-hack colors + color[0]= 0.18f; + color[1]= 0.46f; + color[2]= 0.86f; + } + else { + /* normal, unselected strip - use (hardly noticable) blue tinge */ + // FIXME: hardcoded temp-hack colors + color[0]= 0.11f; + color[1]= 0.15f; + color[2]= 0.19f; + } + } else { - /* normal, unselected strip - use standard strip theme color */ - UI_GetThemeColor3fv(TH_STRIP, color); + /* Action Clip (default/normal type of strip) */ + if ((strip->flag & NLASTRIP_FLAG_ACTIVE) && (adt && (adt->flag & ADT_NLA_EDIT_ON))) { + /* active strip should be drawn green when it is acting as the tweaking strip. + * however, this case should be skipped for when not in EditMode... + */ + // FIXME: hardcoded temp-hack colors + color[0]= 0.3f; + color[1]= 0.95f; + color[2]= 0.1f; + } + else if (strip->flag & NLASTRIP_FLAG_TWEAKUSER) { + /* alert user that this strip is also used by the tweaking track (this is set when going into + * 'editmode' for that strip), since the edits made here may not be what the user anticipated + */ + // FIXME: hardcoded temp-hack colors + color[0]= 0.85f; + color[1]= 0.0f; + color[2]= 0.0f; + } + else if (strip->flag & NLASTRIP_FLAG_SELECT) { + /* selected strip - use theme color for selected */ + UI_GetThemeColor3fv(TH_STRIP_SELECT, color); + } + else { + /* normal, unselected strip - use standard strip theme color */ + UI_GetThemeColor3fv(TH_STRIP, color); + } } } @@ -328,7 +416,7 @@ void draw_nla_main_data (bAnimContext *ac, SpaceNla *snla, ARegion *ar) */ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); - + // TODO: if tweaking some action, use the same color as for the tweaked track (quick hack done for now) if (adt && (adt->flag & ADT_NLA_EDIT_ON)) { // greenish color (same as tweaking strip) - hardcoded for now @@ -351,6 +439,22 @@ void draw_nla_main_data (bAnimContext *ac, SpaceNla *snla, ARegion *ar) glVertex2f(v2d->cur.xmax, yminc+NLACHANNEL_SKIP); glEnd(); + /* draw keyframes in the action */ + nla_action_draw_keyframes(adt, v2d, y); + + /* draw 'embossed' lines above and below the strip for effect */ + /* white base-lines */ + glLineWidth(2.0f); + glColor4f(1.0f, 1.0f, 1.0f, 0.3); + fdrawline(v2d->cur.xmin, yminc+NLACHANNEL_SKIP, v2d->cur.xmax, yminc+NLACHANNEL_SKIP); + fdrawline(v2d->cur.xmin, ymaxc-NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc-NLACHANNEL_SKIP); + + /* black top-lines */ + glLineWidth(1.0f); + glColor3f(0.0f, 0.0f, 0.0f); + fdrawline(v2d->cur.xmin, yminc+NLACHANNEL_SKIP, v2d->cur.xmax, yminc+NLACHANNEL_SKIP); + fdrawline(v2d->cur.xmin, ymaxc-NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc-NLACHANNEL_SKIP); + glDisable(GL_BLEND); } break; diff --git a/source/blender/editors/space_nla/nla_header.c b/source/blender/editors/space_nla/nla_header.c index 1971b062c2b..2cbf3adcba7 100644 --- a/source/blender/editors/space_nla/nla_header.c +++ b/source/blender/editors/space_nla/nla_header.c @@ -182,7 +182,6 @@ static void do_nla_buttons(bContext *C, void *arg, int event) void nla_header_buttons(const bContext *C, ARegion *ar) { SpaceNla *snla= (SpaceNla *)CTX_wm_space_data(C); - Scene *scene= CTX_data_scene(C); ScrArea *sa= CTX_wm_area(C); uiBlock *block; int xco, yco= 3; @@ -254,14 +253,6 @@ void nla_header_buttons(const bContext *C, ARegion *ar) } xco += 98; - /* Tweakmode... */ - // XXX these icons need to be changed - if (scene->flag & SCE_NLA_EDIT_ON) - uiDefIconTextButO(block, BUT, "NLAEDIT_OT_tweakmode_exit", WM_OP_INVOKE_REGION_WIN, ICON_NLA, "Exit TweakMode", xco,yco,130,YIC, "Restore the true active action. (TAB)"); - else - uiDefIconTextButO(block, BUT, "NLAEDIT_OT_tweakmode_enter", WM_OP_INVOKE_REGION_WIN, ICON_EDIT, "Enter TweakMode", xco,yco,130,YIC, "Temporarily set the action referenced by the active strip as the active action so that it can be tweaked. (TAB)"); - xco+= 150; - /* always as last */ UI_view2d_totRect_set(&ar->v2d, xco+XIC+80, ar->v2d.tot.ymax-ar->v2d.tot.ymin); From 3533cda80c7b52f8ffca3e3928bedb5bfa96b320 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Wed, 24 Jun 2009 12:12:11 +0000 Subject: [PATCH 058/114] NLA SoC: Delete Tracks Operator (XKEY / DELKEY) over the channel list This deletes all the strips in the relevant (selected) tracks too. --- .../blender/editors/space_nla/nla_channels.c | 54 +++++++++++++++++++ source/blender/editors/space_nla/nla_draw.c | 5 +- source/blender/editors/space_nla/nla_intern.h | 1 + source/blender/editors/space_nla/nla_ops.c | 5 ++ 4 files changed, 61 insertions(+), 4 deletions(-) diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c index a1c0de1e552..0a2c32b5f52 100644 --- a/source/blender/editors/space_nla/nla_channels.c +++ b/source/blender/editors/space_nla/nla_channels.c @@ -423,4 +423,58 @@ void NLA_OT_add_tracks (wmOperatorType *ot) RNA_def_boolean(ot->srna, "above_selected", 0, "Above Selected", "Add a new NLA Track above every existing selected one."); } +/* ******************** Delete Tracks Operator ***************************** */ +/* Delete selected NLA Tracks */ + +static int nlaedit_delete_tracks_exec (bContext *C, wmOperator *op) +{ + bAnimContext ac; + + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* get a list of the AnimData blocks being shown in the NLA */ + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_SEL); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* delete tracks */ + for (ale= anim_data.first; ale; ale= ale->next) { + NlaTrack *nlt= (NlaTrack *)ale->data; + AnimData *adt= BKE_animdata_from_id(ale->id); + + /* call delete on this track - deletes all strips too */ + free_nlatrack(&adt->nla_tracks, nlt); + } + + /* free temp data */ + BLI_freelistN(&anim_data); + + /* set notifier that things have changed */ + ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); + WM_event_add_notifier(C, NC_SCENE, NULL); + + /* done */ + return OPERATOR_FINISHED; +} + +void NLA_OT_delete_tracks (wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Delete Tracks"; + ot->idname= "NLA_OT_delete_tracks"; + ot->description= "Delete selected NLA-Tracks and the strips they contain."; + + /* api callbacks */ + ot->exec= nlaedit_delete_tracks_exec; + ot->poll= nlaop_poll_tweakmode_off; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + /* *********************************************** */ diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index 5a22da2eb25..51c1960c4c6 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -391,9 +391,6 @@ void draw_nla_main_data (bAnimContext *ac, SpaceNla *snla, ARegion *ar) NlaStrip *strip; int index; - /* draw backdrop? */ - // TODO... - /* draw each strip in the track (if visible) */ for (strip=nlt->strips.first, index=1; strip; strip=strip->next, index++) { if (BKE_nlastrip_within_bounds(strip, v2d->cur.xmin, v2d->cur.xmax)) { @@ -420,7 +417,7 @@ void draw_nla_main_data (bAnimContext *ac, SpaceNla *snla, ARegion *ar) // TODO: if tweaking some action, use the same color as for the tweaked track (quick hack done for now) if (adt && (adt->flag & ADT_NLA_EDIT_ON)) { // greenish color (same as tweaking strip) - hardcoded for now - glColor4f(0.3f, 0.95f, 0.1f, 0.3f); // FIXME: only draw the actual range of the action darker? + glColor4f(0.3f, 0.95f, 0.1f, 0.3f); } else { if (ale->data) diff --git a/source/blender/editors/space_nla/nla_intern.h b/source/blender/editors/space_nla/nla_intern.h index 79ee5396f36..ef37185fd10 100644 --- a/source/blender/editors/space_nla/nla_intern.h +++ b/source/blender/editors/space_nla/nla_intern.h @@ -106,6 +106,7 @@ void NLAEDIT_OT_split(wmOperatorType *ot); void NLA_OT_channels_click(wmOperatorType *ot); void NLA_OT_add_tracks(wmOperatorType *ot); +void NLA_OT_delete_tracks(wmOperatorType *ot); /* **************************************** */ /* nla_ops.c */ diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c index df731e9d0fb..2a6a0c64ea9 100644 --- a/source/blender/editors/space_nla/nla_ops.c +++ b/source/blender/editors/space_nla/nla_ops.c @@ -132,6 +132,7 @@ void nla_operatortypes(void) WM_operatortype_append(NLA_OT_channels_click); WM_operatortype_append(NLA_OT_add_tracks); + WM_operatortype_append(NLA_OT_delete_tracks); /* select */ WM_operatortype_append(NLAEDIT_OT_click_select); @@ -166,6 +167,10 @@ static void nla_keymap_channels (wmWindowManager *wm, ListBase *keymap) WM_keymap_add_item(keymap, "NLA_OT_add_tracks", AKEY, KM_PRESS, KM_SHIFT, 0); RNA_boolean_set(WM_keymap_add_item(keymap, "NLA_OT_add_tracks", AKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0)->ptr, "above_selected", 1); + /* delete tracks */ + WM_keymap_add_item(keymap, "NLA_OT_delete_tracks", XKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "NLA_OT_delete_tracks", DELKEY, KM_PRESS, 0, 0); + /* General Animation Channels keymap (see anim_channels.c) ----------------------- */ /* selection */ /* borderselect - not in tweakmode */ From e5f6a41b1b7125a4c3bc7ef2554c04b768ac765c Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Wed, 24 Jun 2009 12:50:20 +0000 Subject: [PATCH 059/114] NLA SoC: Scale Operators - Clear (Alt-S) and Apply (Ctrl-A) These two operators work only on Action-Clip strips. * Clear (Alt-S) resets the scale of selected strips to 1.0 * Apply (Ctrl-A) applies the scale of the selected strips to their referenced Actions. If this referenced Action is also used by several other strips, a copy of the Action is made, and the scaling is applied to that Action instead. --- source/blender/editors/space_nla/nla_edit.c | 165 +++++++++++++++++- source/blender/editors/space_nla/nla_header.c | 5 + source/blender/editors/space_nla/nla_intern.h | 3 + source/blender/editors/space_nla/nla_ops.c | 7 + 4 files changed, 179 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index 70a033052bd..df30e112b5a 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -46,6 +46,8 @@ #include "BLI_rand.h" #include "BKE_animsys.h" +#include "BKE_action.h" +#include "BKE_fcurve.h" #include "BKE_nla.h" #include "BKE_context.h" #include "BKE_library.h" @@ -55,6 +57,7 @@ #include "BKE_utildefines.h" #include "ED_anim_api.h" +#include "ED_keyframes_edit.h" #include "ED_markers.h" #include "ED_space_api.h" #include "ED_screen.h" @@ -72,6 +75,7 @@ #include "UI_view2d.h" #include "nla_intern.h" // own include +#include "nla_private.h" // FIXME... maybe this shouldn't be included? /* *********************************************** */ /* 'Special' Editing */ @@ -217,7 +221,7 @@ void NLAEDIT_OT_tweakmode_exit (wmOperatorType *ot) } /* *********************************************** */ -/* NLA Editing Operations */ +/* NLA Editing Operations (Constructive/Destructive) */ /* ******************** Add Action-Clip Operator ***************************** */ /* Add a new Action-Clip strip to the active track (or the active block if no space in the track) */ @@ -700,3 +704,162 @@ void NLAEDIT_OT_split (wmOperatorType *ot) } /* *********************************************** */ +/* NLA Editing Operations (Modifying) */ + +/* ******************** Apply Scale Operator ***************************** */ +/* Reset the scaling of the selected strips to 1.0f */ + +/* apply scaling to keyframe */ +static short bezt_apply_nlamapping (BeztEditData *bed, BezTriple *bezt) +{ + /* NLA-strip which has this scaling is stored in bed->data */ + NlaStrip *strip= (NlaStrip *)bed->data; + + /* adjust all the times */ + bezt->vec[0][0]= nlastrip_get_frame(strip, bezt->vec[0][0], 1); + bezt->vec[1][0]= nlastrip_get_frame(strip, bezt->vec[1][0], 1); + bezt->vec[2][0]= nlastrip_get_frame(strip, bezt->vec[2][0], 1); + + /* nothing to return or else we exit */ + return 0; +} + +static int nlaedit_apply_scale_exec (bContext *C, wmOperator *op) +{ + bAnimContext ac; + + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + BeztEditData bed; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* get a list of the editable tracks being shown in the NLA */ + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* init the editing data */ + memset(&bed, 0, sizeof(BeztEditData)); + + /* for each NLA-Track, apply scale of all selected strips */ + for (ale= anim_data.first; ale; ale= ale->next) { + NlaTrack *nlt= (NlaTrack *)ale->data; + NlaStrip *strip; + + for (strip= nlt->strips.first; strip; strip= strip->next) { + /* strip must be selected, and must be action-clip only (transitions don't have scale) */ + if ((strip->flag & NLASTRIP_FLAG_SELECT) && (strip->type == NLASTRIP_TYPE_CLIP)) { + /* if the referenced action is used by other strips, make this strip use its own copy */ + if (strip->act == NULL) + continue; + if (strip->act->id.us > 1) { + /* make a copy of the Action to work on */ + bAction *act= copy_action(strip->act); + + /* set this as the new referenced action, decrementing the users of the old one */ + strip->act->id.us--; + strip->act= act; + } + + /* setup iterator, and iterate over all the keyframes in the action, applying this scaling */ + bed.data= strip; + ANIM_animchanneldata_keys_bezier_loop(&bed, strip->act, ALE_ACT, NULL, bezt_apply_nlamapping, calchandles_fcurve, 0); + + /* clear scale of strip now that it has been applied, but leave everything else alone */ + strip->scale= 1.0f; + } + } + } + + /* free temp data */ + BLI_freelistN(&anim_data); + + /* set notifier that things have changed */ + ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); + WM_event_add_notifier(C, NC_SCENE, NULL); + + /* done */ + return OPERATOR_FINISHED; +} + +void NLAEDIT_OT_apply_scale (wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Apply Scale"; + ot->idname= "NLAEDIT_OT_apply_scale"; + ot->description= "Apply scaling of selected strips to their referenced Actions."; + + /* api callbacks */ + ot->exec= nlaedit_apply_scale_exec; + ot->poll= nlaop_poll_tweakmode_off; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +/* ******************** Clear Scale Operator ***************************** */ +/* Reset the scaling of the selected strips to 1.0f */ + +static int nlaedit_clear_scale_exec (bContext *C, wmOperator *op) +{ + bAnimContext ac; + + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* get a list of the editable tracks being shown in the NLA */ + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* for each NLA-Track, reset scale of all selected strips */ + for (ale= anim_data.first; ale; ale= ale->next) { + NlaTrack *nlt= (NlaTrack *)ale->data; + NlaStrip *strip; + + for (strip= nlt->strips.first; strip; strip= strip->next) { + /* strip must be selected, and must be action-clip only (transitions don't have scale) */ + if ((strip->flag & NLASTRIP_FLAG_SELECT) && (strip->type == NLASTRIP_TYPE_CLIP)) { + PointerRNA strip_ptr; + + RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr); + RNA_float_set(&strip_ptr, "scale", 1.0f); + } + } + } + + /* free temp data */ + BLI_freelistN(&anim_data); + + /* set notifier that things have changed */ + ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); + WM_event_add_notifier(C, NC_SCENE, NULL); + + /* done */ + return OPERATOR_FINISHED; +} + +void NLAEDIT_OT_clear_scale (wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Clear Scale"; + ot->idname= "NLAEDIT_OT_clear_scale"; + ot->description= "Reset scaling of selected strips."; + + /* api callbacks */ + ot->exec= nlaedit_clear_scale_exec; + ot->poll= nlaop_poll_tweakmode_off; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +/* *********************************************** */ diff --git a/source/blender/editors/space_nla/nla_header.c b/source/blender/editors/space_nla/nla_header.c index 2cbf3adcba7..11dfc5575b1 100644 --- a/source/blender/editors/space_nla/nla_header.c +++ b/source/blender/editors/space_nla/nla_header.c @@ -154,6 +154,11 @@ static void nla_editmenu(bContext *C, uiLayout *layout, void *arg_unused) uiItemS(layout); uiItemO(layout, NULL, 0, "NLAEDIT_OT_delete"); + + uiItemS(layout); + + uiItemO(layout, NULL, 0, "NLAEDIT_OT_apply_scale"); + uiItemO(layout, NULL, 0, "NLAEDIT_OT_clear_scale"); } static void nla_addmenu(bContext *C, uiLayout *layout, void *arg_unused) diff --git a/source/blender/editors/space_nla/nla_intern.h b/source/blender/editors/space_nla/nla_intern.h index ef37185fd10..17fad5db47f 100644 --- a/source/blender/editors/space_nla/nla_intern.h +++ b/source/blender/editors/space_nla/nla_intern.h @@ -99,6 +99,9 @@ void NLAEDIT_OT_duplicate(wmOperatorType *ot); void NLAEDIT_OT_delete(wmOperatorType *ot); void NLAEDIT_OT_split(wmOperatorType *ot); +void NLAEDIT_OT_apply_scale(wmOperatorType *ot); +void NLAEDIT_OT_clear_scale(wmOperatorType *ot); + /* **************************************** */ /* nla_channels.c */ diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c index 2a6a0c64ea9..531e049d29a 100644 --- a/source/blender/editors/space_nla/nla_ops.c +++ b/source/blender/editors/space_nla/nla_ops.c @@ -149,6 +149,9 @@ void nla_operatortypes(void) WM_operatortype_append(NLAEDIT_OT_duplicate); WM_operatortype_append(NLAEDIT_OT_delete); WM_operatortype_append(NLAEDIT_OT_split); + + WM_operatortype_append(NLAEDIT_OT_apply_scale); + WM_operatortype_append(NLAEDIT_OT_clear_scale); } /* ************************** registration - keymaps **********************************/ @@ -239,6 +242,10 @@ static void nla_keymap_main (wmWindowManager *wm, ListBase *keymap) /* split */ WM_keymap_add_item(keymap, "NLAEDIT_OT_split", YKEY, KM_PRESS, 0, 0); + /* apply scale */ + WM_keymap_add_item(keymap, "NLAEDIT_OT_apply_scale", AKEY, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "NLAEDIT_OT_clear_scale", SKEY, KM_PRESS, KM_ALT, 0); + /* transform system */ transform_keymap_for_space(wm, keymap, SPACE_NLA); } From a50be876d37d4add34d809ebe6546f0097c17761 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 25 Jun 2009 05:05:35 +0000 Subject: [PATCH 060/114] NLA SoC: Quick crash fix Pointer for accessing settings of active NLA-strip was not getting set. The code for this was accidentally removed during an earlier commit to clean up the poll callbacks here. --- source/blender/editors/space_nla/nla_buttons.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c index 0d5cdf80830..a25f741c193 100644 --- a/source/blender/editors/space_nla/nla_buttons.c +++ b/source/blender/editors/space_nla/nla_buttons.c @@ -207,6 +207,9 @@ static void nla_panel_properties(const bContext *C, Panel *pa) uiLayout *column, *row, *subcol; uiBlock *block; + if (!nla_panel_context(C, NULL, &strip_ptr)) + return; + block= uiLayoutGetBlock(layout); uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL); @@ -259,10 +262,6 @@ static void nla_panel_actclip(const bContext *C, Panel *pa) if (!nla_panel_context(C, NULL, &strip_ptr)) return; - // XXX FIXME: move this check into a poll callback - if (RNA_enum_get(&strip_ptr, "type") != NLASTRIP_TYPE_CLIP) - return; - block= uiLayoutGetBlock(layout); uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL); From deffe4a315f30a8f8a2a2e2f23f16cfcb0ac5f18 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 25 Jun 2009 10:52:09 +0000 Subject: [PATCH 061/114] NLA SoC: Armature Drawing Code Fixes * Compiling broke for some users on this file due to my scaling-fixes commit. Dunno why this didn't give any errors here (silly compiler!) * Restored code to make ghost poses (and supposedly paths) work again. This doesn't totally seem to be the case yet though. --- .../editors/space_view3d/drawarmature.c | 58 ++++++++----------- 1 file changed, 23 insertions(+), 35 deletions(-) diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c index 68a9bf3f555..a4332ea1709 100644 --- a/source/blender/editors/space_view3d/drawarmature.c +++ b/source/blender/editors/space_view3d/drawarmature.c @@ -37,6 +37,7 @@ #include "MEM_guardedalloc.h" +#include "DNA_anim_types.h" #include "DNA_action_types.h" #include "DNA_armature_types.h" #include "DNA_constraint_types.h" @@ -52,6 +53,7 @@ #include "BLI_blenlib.h" #include "BLI_arithb.h" +#include "BKE_animsys.h" #include "BKE_action.h" #include "BKE_armature.h" #include "BKE_constraint.h" @@ -61,6 +63,7 @@ #include "BKE_global.h" #include "BKE_main.h" #include "BKE_modifier.h" +#include "BKE_nla.h" #include "BKE_object.h" #include "BKE_utildefines.h" @@ -2019,10 +2022,9 @@ static void draw_ebones(View3D *v3d, RegionView3D *rv3d, Object *ob, int dt) */ static void draw_pose_paths(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob) { + AnimData *adt= BKE_animdata_from_id(&ob->id); bArmature *arm= ob->data; bPoseChannel *pchan; - // bAction *act; // XXX old animsys - watch it! - // bActionChannel *achan; ActKeyColumn *ak; ListBase keys; float *fp, *fp_start; @@ -2168,14 +2170,11 @@ static void draw_pose_paths(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec /* build list of all keyframes in active action for pchan */ keys.first = keys.last = NULL; - #if 0 // XXX old animation system - act= ob->action; - if (act) { - achan= get_action_channel(act, pchan->name); - if (achan) - ipo_to_keylist(achan->ipo, &keys, NULL, NULL); + if (adt) { + bActionGroup *agrp= action_groups_find_named(adt->action, pchan->name); + if (agrp) + agroup_to_keylist(agrp, &keys, NULL, NULL); } - #endif // XXX old animation system /* Draw slightly-larger yellow dots at each keyframe */ UI_ThemeColor(TH_VERTEX_SELECT); @@ -2254,6 +2253,7 @@ static void ghost_poses_tag_unselected(Object *ob, short unset) static void draw_ghost_poses_range(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base) { Object *ob= base->object; + AnimData *adt= BKE_animdata_from_id(&ob->id); bArmature *arm= ob->data; bPose *posen, *poseo; float start, end, stepsize, range, colfac; @@ -2290,7 +2290,7 @@ static void draw_ghost_poses_range(Scene *scene, View3D *v3d, RegionView3D *rv3d colfac = (end - (float)CFRA) / range; UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128-(int)(120.0*sqrt(colfac))); - //do_all_pose_actions(scene, ob); // XXX old animation system + 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); } @@ -2315,7 +2315,8 @@ static void draw_ghost_poses_range(Scene *scene, View3D *v3d, RegionView3D *rv3d static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base) { Object *ob= base->object; - bAction *act= ob->action; // XXX old animsys stuff... watch it! + AnimData *adt= BKE_animdata_from_id(&ob->id); + bAction *act= (adt) ? adt->action : NULL; bArmature *arm= ob->data; bPose *posen, *poseo; ListBase keys= {NULL, NULL}; @@ -2366,7 +2367,7 @@ static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, RegionView3D *rv3d, CFRA= (int)ak->cfra; - //do_all_pose_actions(scene, ob); // XXX old animation system + 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); } @@ -2391,38 +2392,27 @@ static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, RegionView3D *rv3d, static void draw_ghost_poses(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base) { Object *ob= base->object; + AnimData *adt= BKE_animdata_from_id(&ob->id); bArmature *arm= ob->data; bPose *posen, *poseo; - //bActionStrip *strip; float cur, start, end, stepsize, range, colfac, actframe, ctime; - int cfrao, maptime, flago; + int cfrao, flago; /* pre conditions, get an action with sufficient frames */ - //if (ob->action==NULL) - // return; + if ELEM(NULL, adt, adt->action) + return; - calc_action_range(ob->action, &start, &end, 0); + calc_action_range(adt->action, &start, &end, 0); if (start == end) return; stepsize= (float)(arm->ghostsize); range= (float)(arm->ghostep)*stepsize + 0.5f; /* plus half to make the for loop end correct */ -#if 0 // XXX old animation system - /* we only map time for armature when an active strip exists */ - for (strip=ob->nlastrips.first; strip; strip=strip->next) - if (strip->flag & ACTSTRIP_ACTIVE) - break; -#endif // XXX old animsys - - //maptime= (strip!=NULL); - maptime= 0; - /* store values */ ob->flag &= ~OB_POSEMODE; cfrao= CFRA; - if (maptime) actframe= get_action_frame(ob, (float)CFRA); - else actframe= (float)CFRA; + actframe= BKE_nla_tweakedit_remap(adt, (float)CFRA, 0); flago= arm->flag; arm->flag &= ~(ARM_DRAWNAMES|ARM_DRAWAXES); @@ -2444,11 +2434,10 @@ static void draw_ghost_poses(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base /* only within action range */ if (actframe+ctime >= start && actframe+ctime <= end) { - if (maptime) CFRA= (int)get_action_frame_inv(ob, actframe+ctime); - else CFRA= (int)floor(actframe+ctime); + CFRA= (int)BKE_nla_tweakedit_remap(adt, actframe+ctime, 1); if (CFRA != cfrao) { - //do_all_pose_actions(scene, ob); // xxx old animation system crap + 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); } @@ -2460,11 +2449,10 @@ static void draw_ghost_poses(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base /* only within action range */ if ((actframe-ctime >= start) && (actframe-ctime <= end)) { - if (maptime) CFRA= (int)get_action_frame_inv(ob, actframe-ctime); - else CFRA= (int)floor(actframe-ctime); + CFRA= (int)BKE_nla_tweakedit_remap(adt, actframe-ctime, 1); if (CFRA != cfrao) { - //do_all_pose_actions(scene, ob); // XXX old animation system crap... + 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); } From 6510da4ce2c7d3ffef9d95d7adedd31f59c1fc4b Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 25 Jun 2009 12:30:49 +0000 Subject: [PATCH 062/114] NLA SoC: Fix transforms for transition strips. --- .../editors/transform/transform_conversions.c | 68 ++++++++++--------- .../editors/transform/transform_generics.c | 16 ++++- source/blender/makesrna/intern/rna_nla.c | 49 ++++++++++--- 3 files changed, 88 insertions(+), 45 deletions(-) diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 08ce1b1d554..3bc950d5863 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -2620,9 +2620,12 @@ static void createTransNlaData(bContext *C, TransInfo *t) /* only consider selected strips */ for (strip= nlt->strips.first; strip; strip= strip->next) { // TODO: we can make strips have handles later on... - if (strip->flag & NLASTRIP_FLAG_SELECT) { - if (FrameOnMouseSide(side, strip->start, (float)CFRA)) count++; - if (FrameOnMouseSide(side, strip->end, (float)CFRA)) count++; + /* transition strips can't get directly transformed */ + if (strip->type != NLASTRIP_TYPE_TRANSITION) { + if (strip->flag & NLASTRIP_FLAG_SELECT) { + if (FrameOnMouseSide(side, strip->start, (float)CFRA)) count++; + if (FrameOnMouseSide(side, strip->end, (float)CFRA)) count++; + } } } } @@ -2652,34 +2655,37 @@ static void createTransNlaData(bContext *C, TransInfo *t) /* only consider selected strips */ for (strip= nlt->strips.first; strip; strip= strip->next) { // TODO: we can make strips have handles later on... - if (strip->flag & NLASTRIP_FLAG_SELECT) { - if (FrameOnMouseSide(side, strip->start, (float)CFRA)) - { - /* init the 'extra' data for NLA strip handles first */ - tdn->strip= strip; - tdn->val= strip->start; - tdn->handle= 0; - - /* now, link the transform data up to this data */ - td->val= &tdn->val; - td->ival= tdn->val; - td->extra= tdn; - td++; - tdn++; - } - if (FrameOnMouseSide(side, strip->end, (float)CFRA)) - { - /* init the 'extra' data for NLA strip handles first */ - tdn->strip= strip; - tdn->val= strip->end; - tdn->handle= 1; - - /* now, link the transform data up to this data */ - td->val= &tdn->val; - td->ival= tdn->val; - td->extra= tdn; - td++; - tdn++; + /* transition strips can't get directly transformed */ + if (strip->type != NLASTRIP_TYPE_TRANSITION) { + if (strip->flag & NLASTRIP_FLAG_SELECT) { + if (FrameOnMouseSide(side, strip->start, (float)CFRA)) + { + /* init the 'extra' data for NLA strip handles first */ + tdn->strip= strip; + tdn->val= strip->start; + tdn->handle= 0; + + /* now, link the transform data up to this data */ + td->val= &tdn->val; + td->ival= tdn->val; + td->extra= tdn; + td++; + tdn++; + } + if (FrameOnMouseSide(side, strip->end, (float)CFRA)) + { + /* init the 'extra' data for NLA strip handles first */ + tdn->strip= strip; + tdn->val= strip->end; + tdn->handle= 1; + + /* now, link the transform data up to this data */ + td->val= &tdn->val; + td->ival= tdn->val; + td->extra= tdn; + td++; + tdn++; + } } } } diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index db7c6d6ee99..1474a30fbed 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -358,11 +358,21 @@ void recalcData(TransInfo *t) * ones (i.e. don't go through RNA), as we get some artifacts... */ if (t->state == TRANS_CANCEL) { - /* write the value set by the transform tools to the appropriate property using RNA */ - if (tdn->handle) + /* clear the values by directly overwriting the originals, but also need to restore + * endpoints of neighboring transition-strips + */ + if (tdn->handle) { strip->end= tdn->val; - else + + if ((strip->next) && (strip->next->type == NLASTRIP_TYPE_TRANSITION)) + strip->next->start= tdn->val; + } + else { strip->start= tdn->val; + + if ((strip->prev) && (strip->prev->type == NLASTRIP_TYPE_TRANSITION)) + strip->prev->end= tdn->val; + } } else { PointerRNA strip_ptr; diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c index dacd257dc17..84a84492ea3 100644 --- a/source/blender/makesrna/intern/rna_nla.c +++ b/source/blender/makesrna/intern/rna_nla.c @@ -40,17 +40,30 @@ #include #include +/* temp constant defined for these funcs only... */ +#define NLASTRIP_MIN_LEN_THRESH 0.1f + static void rna_NlaStrip_start_frame_set(PointerRNA *ptr, float value) { NlaStrip *data= (NlaStrip*)ptr->data; /* clamp value to lie within valid limits * - cannot start past the end of the strip + some flexibility threshold - * - cannot start before the previous strip (if present) ends + * - cannot start before the previous strip (if present) ends + * -> but if it was a transition, we could go up to the start of the strip + some flexibility threshold + * as long as we re-adjust the transition afterwards * - minimum frame is -MAXFRAME so that we don't get clipping on frame 0 */ if (data->prev) { - CLAMP(value, data->prev->end, data->end-0.1f); + if (data->prev->type == NLASTRIP_TYPE_TRANSITION) { + CLAMP(value, data->prev->start+NLASTRIP_MIN_LEN_THRESH, data->end-NLASTRIP_MIN_LEN_THRESH); + + /* readjust the transition to stick to the endpoints of the action-clips */ + data->prev->end= value; + } + else { + CLAMP(value, data->prev->end, data->end-NLASTRIP_MIN_LEN_THRESH); + } } else { CLAMP(value, -MAXFRAME, data->end); @@ -61,28 +74,42 @@ static void rna_NlaStrip_start_frame_set(PointerRNA *ptr, float value) static void rna_NlaStrip_end_frame_set(PointerRNA *ptr, float value) { NlaStrip *data= (NlaStrip*)ptr->data; - float len, actlen; /* clamp value to lie within valid limits * - must not have zero or negative length strip, so cannot start before the first frame * + some minimum-strip-length threshold * - cannot end later than the start of the next strip (if present) + * -> but if it was a transition, we could go up to the start of the end - some flexibility threshold + * as long as we re-adjust the transition afterwards */ if (data->next) { - CLAMP(value, data->start+0.1f, data->next->start); + if (data->next->type == NLASTRIP_TYPE_TRANSITION) { + CLAMP(value, data->start+NLASTRIP_MIN_LEN_THRESH, data->next->end-NLASTRIP_MIN_LEN_THRESH); + + /* readjust the transition to stick to the endpoints of the action-clips */ + data->next->start= value; + } + else { + CLAMP(value, data->start+NLASTRIP_MIN_LEN_THRESH, data->next->start); + } } else { - CLAMP(value, data->start+0.1f, MAXFRAME); + CLAMP(value, data->start+NLASTRIP_MIN_LEN_THRESH, MAXFRAME); } data->end= value; - /* calculate the lengths the strip and its action (if applicable) */ - len= data->end - data->start; - actlen= data->actend - data->actstart; - if (IS_EQ(actlen, 0.0f)) actlen= 1.0f; - /* now, adjust the 'scale' setting to reflect this (so that this change can be valid) */ - data->scale= len / ((actlen) * data->repeat); + /* calculate the lengths the strip and its action (if applicable) */ + if (data->type == NLASTRIP_TYPE_CLIP) { + float len, actlen; + + len= data->end - data->start; + actlen= data->actend - data->actstart; + if (IS_EQ(actlen, 0.0f)) actlen= 1.0f; + + /* now, adjust the 'scale' setting to reflect this (so that this change can be valid) */ + data->scale= len / ((actlen) * data->repeat); + } } static void rna_NlaStrip_scale_set(PointerRNA *ptr, float value) From 13d18c5f777710fc396adde64725ecc5ecee019b Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sat, 27 Jun 2009 00:40:25 +0000 Subject: [PATCH 063/114] NLA SoC: Theme colours in old defaults files for NLA now get replaced with the nice new colours --- source/blender/editors/interface/resources.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 4b2d5af956d..2798f7a473f 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -1075,19 +1075,6 @@ void init_userdef_do_versions(void) SETCOL(btheme->ttime.cframe, 0x60, 0xc0, 0x40, 255); } } - if ((G.main->versionfile < 245) || (G.main->versionfile == 245 && G.main->subversionfile < 11)) { - bTheme *btheme; - for (btheme= U.themes.first; btheme; btheme= btheme->next) { - /* these should all use the same color */ - SETCOL(btheme->tv3d.cframe, 0x60, 0xc0, 0x40, 255); - SETCOL(btheme->tipo.cframe, 0x60, 0xc0, 0x40, 255); - SETCOL(btheme->tact.cframe, 0x60, 0xc0, 0x40, 255); - SETCOL(btheme->tnla.cframe, 0x60, 0xc0, 0x40, 255); - SETCOL(btheme->tseq.cframe, 0x60, 0xc0, 0x40, 255); - SETCOL(btheme->tsnd.cframe, 0x60, 0xc0, 0x40, 255); - SETCOL(btheme->ttime.cframe, 0x60, 0xc0, 0x40, 255); - } - } if ((G.main->versionfile < 245) || (G.main->versionfile == 245 && G.main->subversionfile < 13)) { bTheme *btheme; for (btheme= U.themes.first; btheme; btheme= btheme->next) { @@ -1210,6 +1197,13 @@ void init_userdef_do_versions(void) /* Graph Editor - Group Channel color */ SETCOL(btheme->tipo.group, 79, 101, 73, 255); SETCOL(btheme->tipo.group_active, 135, 177, 125, 255); + + /* Nla Editor - (Object) Channel color */ + SETCOL(btheme->tnla.ds_channel, 82, 96, 110, 255); + SETCOL(btheme->tnla.ds_subchannel, 124, 137, 150, 255); + /* NLA Editor - New Strip colors */ + SETCOL(btheme->tnla.strip, 12, 10, 10, 128); + SETCOL(btheme->tnla.strip_select, 255, 140, 0, 255); } /* adjust grease-pencil distances */ From f508319fc8c54e918446482392ab6e1b01c63fe6 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sat, 27 Jun 2009 04:56:20 +0000 Subject: [PATCH 064/114] NLA SoC: Apply-Scale Operator now recalculates action length after scale is applied --- source/blender/editors/space_nla/nla_edit.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index df30e112b5a..44528714732 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -769,8 +769,12 @@ static int nlaedit_apply_scale_exec (bContext *C, wmOperator *op) bed.data= strip; ANIM_animchanneldata_keys_bezier_loop(&bed, strip->act, ALE_ACT, NULL, bezt_apply_nlamapping, calchandles_fcurve, 0); - /* clear scale of strip now that it has been applied, but leave everything else alone */ + /* clear scale of strip now that it has been applied, + * and recalculate the extents of the action now that it has been scaled + * but leave everything else alone + */ strip->scale= 1.0f; + calc_action_range(strip->act, &strip->actstart, &strip->actend, 1); } } } From d3557fc487bc5e5c02c9758b6a05200575e82e84 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sat, 27 Jun 2009 12:35:11 +0000 Subject: [PATCH 065/114] NLA SoC: Recoded the strip<->global time conversion code * Strip evaluation now takes into account repeats * Increasing the number of repeats lengthens the strip, while decreasing the number of repeats does the opposite. TODO: - inverse correction doesn't take into account repeats != 1, so tweaking strips with repeats is currently not recommended! --- source/blender/blenkernel/intern/nla.c | 44 ++++++++++++++++++------ source/blender/makesrna/intern/rna_nla.c | 24 ++++++++++++- 2 files changed, 56 insertions(+), 12 deletions(-) diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 747113b6531..760139bee15 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -331,7 +331,7 @@ NlaStrip *add_nlastrip_to_stack (AnimData *adt, bAction *act) */ static float nlastrip_get_frame_actionclip (NlaStrip *strip, float cframe, short invert) { - float length, actlength, repeat, scale; + float actlength, repeat, scale; /* get number of repeats */ if (IS_EQ(strip->repeat, 0.0f)) strip->repeat = 1.0f; @@ -345,24 +345,46 @@ static float nlastrip_get_frame_actionclip (NlaStrip *strip, float cframe, short actlength = strip->actend - strip->actstart; if (IS_EQ(actlength, 0.0f)) actlength = 1.0f; - /* length of strip */ - length= actlength * scale * repeat; - if (IS_EQ(length, 0.0f)) length= strip->end - strip->start; - /* reversed = play strip backwards */ if (strip->flag & NLASTRIP_FLAG_REVERSE) { /* invert = convert action-strip time to global time */ if (invert) - return length*(strip->actend - cframe)/(repeat*actlength) + strip->start; - else - return strip->actend - repeat*actlength*(cframe - strip->start)/length; + return scale*(strip->actend - cframe) + strip->start; // FIXME: this doesn't work for multiple repeats yet + else { + if (IS_EQ(cframe, strip->end) && IS_EQ(strip->repeat, ((int)strip->repeat))) { + /* this case prevents the motion snapping back to the first frame at the end of the strip + * by catching the case where repeats is a whole number, which means that the end of the strip + * could also be interpreted as the end of the start of a repeat + */ + return strip->actstart; + } + else { + /* - the 'fmod(..., actlength*scale)' is needed to get the repeats working + * - the '/ scale' is needed to ensure that scaling influences the timing within the repeat + */ + return strip->actend - fmod(cframe - strip->start, actlength*scale) / scale; + } + } } else { /* invert = convert action-strip time to global time */ if (invert) - return length*(cframe - strip->actstart)/(repeat*actlength) + strip->start; - else - return repeat*actlength*(cframe - strip->start)/length + strip->actstart; + return scale*(cframe - strip->actstart) + strip->start; // FIXME: this doesn't work for mutiple repeats yet + else { + if (IS_EQ(cframe, strip->end) && IS_EQ(strip->repeat, ((int)strip->repeat))) { + /* this case prevents the motion snapping back to the first frame at the end of the strip + * by catching the case where repeats is a whole number, which means that the end of the strip + * could also be interpreted as the end of the start of a repeat + */ + return strip->actend; + } + else { + /* - the 'fmod(..., actlength*scale)' is needed to get the repeats working + * - the '/ scale' is needed to ensure that scaling influences the timing within the repeat + */ + return strip->actstart + fmod(cframe - strip->start, actlength*scale) / scale; + } + } } } diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c index 84a84492ea3..5dc624b67bc 100644 --- a/source/blender/makesrna/intern/rna_nla.c +++ b/source/blender/makesrna/intern/rna_nla.c @@ -133,6 +133,27 @@ static void rna_NlaStrip_scale_set(PointerRNA *ptr, float value) printf("NlaStrip Set Scale Error (in RNA): Scale = %0.4f, Repeat = %0.4f \n", data->scale, data->repeat); } +static void rna_NlaStrip_repeat_set(PointerRNA *ptr, float value) +{ + NlaStrip *data= (NlaStrip*)ptr->data; + float actlen, mapping; + + /* set scale value */ + CLAMP(value, 0.01f, 1000.0f); /* NOTE: these need to be synced with the values in the property definition in rna_def_nlastrip() */ + data->repeat= value; + + /* calculate existing factors */ + actlen= data->actend - data->actstart; + if (IS_EQ(actlen, 0.0f)) actlen= 1.0f; + mapping= data->scale * data->repeat; + + /* adjust endpoint of strip in response to this */ + if (IS_EQ(mapping, 0.0f) == 0) + data->end = (actlen * mapping) + data->start; + else + printf("NlaStrip Set Repeat Error (in RNA): Scale = %0.4f, Repeat = %0.4f \n", data->scale, data->repeat); +} + static void rna_NlaStrip_blend_in_set(PointerRNA *ptr, float value) { NlaStrip *data= (NlaStrip*)ptr->data; @@ -265,7 +286,8 @@ void rna_def_nlastrip(BlenderRNA *brna) /* Action Reuse */ prop= RNA_def_property(srna, "repeat", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "repeat"); - RNA_def_property_range(prop, 1.0f, 1000.0f); /* these limits have currently be chosen arbitarily, but could be extended (minimum should still be > 0 though) if needed... */ + RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_repeat_set", NULL); + RNA_def_property_range(prop, 0.1f, 1000.0f); /* these limits have currently be chosen arbitarily, but could be extended (minimum should still be > 0 though) if needed... */ RNA_def_property_ui_text(prop, "Repeat", "Number of times to repeat the "); prop= RNA_def_property(srna, "scale", PROP_FLOAT, PROP_NONE); From bc0cd9607e1e2d25f92216332d73c23ef1e7c786 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sat, 27 Jun 2009 13:00:22 +0000 Subject: [PATCH 066/114] NLA SoC: Move Strips Up/Down Operators These operators may be temporary only, depending on if a workable solution via transform is found. * PageUp moves strips into the track above if there's space * PageDown moves strips into the track below if there's space * Also fixed a button-alignment bug in the DopeSheet header --- .../editors/space_action/action_header.c | 3 +- source/blender/editors/space_nla/nla_edit.c | 154 ++++++++++++++++++ source/blender/editors/space_nla/nla_header.c | 5 + source/blender/editors/space_nla/nla_intern.h | 3 + source/blender/editors/space_nla/nla_ops.c | 9 + 5 files changed, 173 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/space_action/action_header.c b/source/blender/editors/space_action/action_header.c index a9ce145088d..62e7a2d8e3f 100644 --- a/source/blender/editors/space_action/action_header.c +++ b/source/blender/editors/space_action/action_header.c @@ -398,7 +398,8 @@ void action_header_buttons(const bContext *C, ARegion *ar) /* COPY PASTE */ uiBlockBeginAlign(block); uiDefIconButO(block, BUT, "ACT_OT_copy", WM_OP_INVOKE_REGION_WIN, ICON_COPYDOWN, xco,yco,XIC,YIC, "Copies the selected keyframes to the buffer."); - uiDefIconButO(block, BUT, "ACT_OT_paste", WM_OP_INVOKE_REGION_WIN, ICON_COPYDOWN, xco,yco,XIC,YIC, "Pastes the keyframes from the buffer into the selected channels."); + xco += XIC; + uiDefIconButO(block, BUT, "ACT_OT_paste", WM_OP_INVOKE_REGION_WIN, ICON_PASTEDOWN, xco,yco,XIC,YIC, "Pastes the keyframes from the buffer into the selected channels."); uiBlockEndAlign(block); xco += (XIC + 8); diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index 44528714732..efde2d0b537 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -706,6 +706,160 @@ void NLAEDIT_OT_split (wmOperatorType *ot) /* *********************************************** */ /* NLA Editing Operations (Modifying) */ +/* ******************** Move Strips Up Operator ************************** */ +/* Tries to move the selected strips into the track above if possible. */ + +static int nlaedit_move_up_exec (bContext *C, wmOperator *op) +{ + bAnimContext ac; + + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + BeztEditData bed; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* get a list of the editable tracks being shown in the NLA */ + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* init the editing data */ + memset(&bed, 0, sizeof(BeztEditData)); + + /* since we're potentially moving strips from lower tracks to higher tracks, we should + * loop over the tracks in reverse order to avoid moving earlier strips up multiple tracks + */ + for (ale= anim_data.last; ale; ale= ale->prev) { + NlaTrack *nlt= (NlaTrack *)ale->data; + NlaTrack *nltn= nlt->next; + NlaStrip *strip, *stripn; + + /* if this track has no tracks after it, skip for now... */ + if (nltn == NULL) + continue; + + /* for every selected strip, try to move */ + for (strip= nlt->strips.first; strip; strip= stripn) { + stripn= strip->next; + + if (strip->flag & NLASTRIP_FLAG_SELECT) { + /* check if the track above has room for this strip */ + if (BKE_nlatrack_has_space(nltn, strip->start, strip->end)) { + /* remove from its current track, and add to the one above (it 'should' work, so no need to worry) */ + BLI_remlink(&nlt->strips, strip); + BKE_nlatrack_add_strip(nltn, strip); + } + } + } + } + + /* free temp data */ + BLI_freelistN(&anim_data); + + /* set notifier that things have changed */ + ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); + WM_event_add_notifier(C, NC_SCENE, NULL); + + /* done */ + return OPERATOR_FINISHED; +} + +void NLAEDIT_OT_move_up (wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Move Strips Up"; + ot->idname= "NLAEDIT_OT_move_up"; + ot->description= "Move selected strips up a track if there's room."; + + /* api callbacks */ + ot->exec= nlaedit_move_up_exec; + ot->poll= nlaop_poll_tweakmode_off; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +/* ******************** Move Strips Down Operator ************************** */ +/* Tries to move the selected strips into the track above if possible. */ + +static int nlaedit_move_down_exec (bContext *C, wmOperator *op) +{ + bAnimContext ac; + + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + BeztEditData bed; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* get a list of the editable tracks being shown in the NLA */ + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* init the editing data */ + memset(&bed, 0, sizeof(BeztEditData)); + + /* loop through the tracks in normal order, since we're pushing strips down, + * strips won't get operated on twice + */ + for (ale= anim_data.first; ale; ale= ale->next) { + NlaTrack *nlt= (NlaTrack *)ale->data; + NlaTrack *nltp= nlt->prev; + NlaStrip *strip, *stripn; + + /* if this track has no tracks before it, skip for now... */ + if (nltp == NULL) + continue; + + /* for every selected strip, try to move */ + for (strip= nlt->strips.first; strip; strip= stripn) { + stripn= strip->next; + + if (strip->flag & NLASTRIP_FLAG_SELECT) { + /* check if the track below has room for this strip */ + if (BKE_nlatrack_has_space(nltp, strip->start, strip->end)) { + /* remove from its current track, and add to the one above (it 'should' work, so no need to worry) */ + BLI_remlink(&nlt->strips, strip); + BKE_nlatrack_add_strip(nltp, strip); + } + } + } + } + + /* free temp data */ + BLI_freelistN(&anim_data); + + /* set notifier that things have changed */ + ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); + WM_event_add_notifier(C, NC_SCENE, NULL); + + /* done */ + return OPERATOR_FINISHED; +} + +void NLAEDIT_OT_move_down (wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Move Strips Down"; + ot->idname= "NLAEDIT_OT_move_down"; + ot->description= "Move selected strips down a track if there's room."; + + /* api callbacks */ + ot->exec= nlaedit_move_down_exec; + ot->poll= nlaop_poll_tweakmode_off; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + /* ******************** Apply Scale Operator ***************************** */ /* Reset the scaling of the selected strips to 1.0f */ diff --git a/source/blender/editors/space_nla/nla_header.c b/source/blender/editors/space_nla/nla_header.c index 11dfc5575b1..939e886abeb 100644 --- a/source/blender/editors/space_nla/nla_header.c +++ b/source/blender/editors/space_nla/nla_header.c @@ -159,6 +159,11 @@ static void nla_editmenu(bContext *C, uiLayout *layout, void *arg_unused) uiItemO(layout, NULL, 0, "NLAEDIT_OT_apply_scale"); uiItemO(layout, NULL, 0, "NLAEDIT_OT_clear_scale"); + + uiItemS(layout); + + uiItemO(layout, NULL, 0, "NLAEDIT_OT_move_up"); + uiItemO(layout, NULL, 0, "NLAEDIT_OT_move_down"); } static void nla_addmenu(bContext *C, uiLayout *layout, void *arg_unused) diff --git a/source/blender/editors/space_nla/nla_intern.h b/source/blender/editors/space_nla/nla_intern.h index 17fad5db47f..7056139d734 100644 --- a/source/blender/editors/space_nla/nla_intern.h +++ b/source/blender/editors/space_nla/nla_intern.h @@ -99,6 +99,9 @@ void NLAEDIT_OT_duplicate(wmOperatorType *ot); void NLAEDIT_OT_delete(wmOperatorType *ot); void NLAEDIT_OT_split(wmOperatorType *ot); +void NLAEDIT_OT_move_up(wmOperatorType *ot); +void NLAEDIT_OT_move_down(wmOperatorType *ot); + void NLAEDIT_OT_apply_scale(wmOperatorType *ot); void NLAEDIT_OT_clear_scale(wmOperatorType *ot); diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c index 531e049d29a..35db79a0b38 100644 --- a/source/blender/editors/space_nla/nla_ops.c +++ b/source/blender/editors/space_nla/nla_ops.c @@ -150,6 +150,9 @@ void nla_operatortypes(void) WM_operatortype_append(NLAEDIT_OT_delete); WM_operatortype_append(NLAEDIT_OT_split); + WM_operatortype_append(NLAEDIT_OT_move_up); + WM_operatortype_append(NLAEDIT_OT_move_down); + WM_operatortype_append(NLAEDIT_OT_apply_scale); WM_operatortype_append(NLAEDIT_OT_clear_scale); } @@ -242,8 +245,14 @@ static void nla_keymap_main (wmWindowManager *wm, ListBase *keymap) /* split */ WM_keymap_add_item(keymap, "NLAEDIT_OT_split", YKEY, KM_PRESS, 0, 0); + /* move up */ + WM_keymap_add_item(keymap, "NLAEDIT_OT_move_up", PAGEUPKEY, KM_PRESS, 0, 0); + /* move down */ + WM_keymap_add_item(keymap, "NLAEDIT_OT_move_down", PAGEDOWNKEY, KM_PRESS, 0, 0); + /* apply scale */ WM_keymap_add_item(keymap, "NLAEDIT_OT_apply_scale", AKEY, KM_PRESS, KM_CTRL, 0); + /* clear scale */ WM_keymap_add_item(keymap, "NLAEDIT_OT_clear_scale", SKEY, KM_PRESS, KM_ALT, 0); /* transform system */ From 61e30f0f001285dcbf0c7ec8ba44151544bfc8d9 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sun, 28 Jun 2009 03:13:01 +0000 Subject: [PATCH 067/114] NLA SoC: Renamed NLA-Editor operators to be more in line with those in other editors --- .../blender/editors/space_nla/nla_buttons.c | 4 +- source/blender/editors/space_nla/nla_edit.c | 46 ++++++------ source/blender/editors/space_nla/nla_header.c | 32 ++++----- source/blender/editors/space_nla/nla_intern.h | 30 ++++---- source/blender/editors/space_nla/nla_ops.c | 70 +++++++++---------- source/blender/editors/space_nla/nla_select.c | 16 ++--- 6 files changed, 99 insertions(+), 99 deletions(-) diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c index a25f741c193..003eba64ed9 100644 --- a/source/blender/editors/space_nla/nla_buttons.c +++ b/source/blender/editors/space_nla/nla_buttons.c @@ -381,10 +381,10 @@ static int nla_properties(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void NLAEDIT_OT_properties(wmOperatorType *ot) +void NLA_OT_properties(wmOperatorType *ot) { ot->name= "Properties"; - ot->idname= "NLAEDIT_OT_properties"; + ot->idname= "NLA_OT_properties"; ot->exec= nla_properties; ot->poll= ED_operator_nla_active; diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index efde2d0b537..bcf3bd4746a 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -139,11 +139,11 @@ static int nlaedit_enable_tweakmode_exec (bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void NLAEDIT_OT_tweakmode_enter (wmOperatorType *ot) +void NLA_OT_tweakmode_enter (wmOperatorType *ot) { /* identifiers */ ot->name= "Enter Tweak Mode"; - ot->idname= "NLAEDIT_OT_tweakmode_enter"; + ot->idname= "NLA_OT_tweakmode_enter"; ot->description= "Enter tweaking mode for the action referenced by the active strip."; /* api callbacks */ @@ -205,11 +205,11 @@ static int nlaedit_disable_tweakmode_exec (bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void NLAEDIT_OT_tweakmode_exit (wmOperatorType *ot) +void NLA_OT_tweakmode_exit (wmOperatorType *ot) { /* identifiers */ ot->name= "Exit Tweak Mode"; - ot->idname= "NLAEDIT_OT_tweakmode_exit"; + ot->idname= "NLA_OT_tweakmode_exit"; ot->description= "Exit tweaking mode for the action referenced by the active strip."; /* api callbacks */ @@ -239,7 +239,7 @@ static int nlaedit_add_actionclip_invoke (bContext *C, wmOperator *op, wmEvent * /* loop through Actions in Main database, adding as items in the menu */ for (act= m->action.first; act; act= act->id.next) - uiItemStringO(layout, act->id.name+2, 0, "NLAEDIT_OT_add_actionclip", "action", act->id.name); + uiItemStringO(layout, act->id.name+2, 0, "NLA_OT_add_actionclip", "action", act->id.name); uiItemS(layout); uiPupMenuEnd(C, pup); @@ -322,11 +322,11 @@ static int nlaedit_add_actionclip_exec (bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void NLAEDIT_OT_add_actionclip (wmOperatorType *ot) +void NLA_OT_add_actionclip (wmOperatorType *ot) { /* identifiers */ ot->name= "Add Action Strip"; - ot->idname= "NLAEDIT_OT_add_actionclip"; + ot->idname= "NLA_OT_add_actionclip"; ot->description= "Add an Action-Clip strip (i.e. an NLA Strip referencing an Action) to the active track."; /* api callbacks */ @@ -431,11 +431,11 @@ static int nlaedit_add_transition_exec (bContext *C, wmOperator *op) } } -void NLAEDIT_OT_add_transition (wmOperatorType *ot) +void NLA_OT_add_transition (wmOperatorType *ot) { /* identifiers */ ot->name= "Add Transition"; - ot->idname= "NLAEDIT_OT_add_transition"; + ot->idname= "NLA_OT_add_transition"; ot->description= "Add a transition strip between two adjacent selected strips."; /* api callbacks */ @@ -529,11 +529,11 @@ static int nlaedit_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_FINISHED; } -void NLAEDIT_OT_duplicate (wmOperatorType *ot) +void NLA_OT_duplicate (wmOperatorType *ot) { /* identifiers */ ot->name= "Duplicate Strips"; - ot->idname= "NLAEDIT_OT_duplicate"; + ot->idname= "NLA_OT_duplicate"; ot->description= "Duplicate selected NLA-Strips, adding the new strips in new tracks above the originals."; /* api callbacks */ @@ -592,11 +592,11 @@ static int nlaedit_delete_exec (bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void NLAEDIT_OT_delete (wmOperatorType *ot) +void NLA_OT_delete (wmOperatorType *ot) { /* identifiers */ ot->name= "Delete Strips"; - ot->idname= "NLAEDIT_OT_delete"; + ot->idname= "NLA_OT_delete"; ot->description= "Delete selected strips."; /* api callbacks */ @@ -688,11 +688,11 @@ static int nlaedit_split_exec (bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void NLAEDIT_OT_split (wmOperatorType *ot) +void NLA_OT_split (wmOperatorType *ot) { /* identifiers */ ot->name= "Split Strips"; - ot->idname= "NLAEDIT_OT_split"; + ot->idname= "NLA_OT_split"; ot->description= "Split selected strips at their midpoints."; /* api callbacks */ @@ -768,11 +768,11 @@ static int nlaedit_move_up_exec (bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void NLAEDIT_OT_move_up (wmOperatorType *ot) +void NLA_OT_move_up (wmOperatorType *ot) { /* identifiers */ ot->name= "Move Strips Up"; - ot->idname= "NLAEDIT_OT_move_up"; + ot->idname= "NLA_OT_move_up"; ot->description= "Move selected strips up a track if there's room."; /* api callbacks */ @@ -845,11 +845,11 @@ static int nlaedit_move_down_exec (bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void NLAEDIT_OT_move_down (wmOperatorType *ot) +void NLA_OT_move_down (wmOperatorType *ot) { /* identifiers */ ot->name= "Move Strips Down"; - ot->idname= "NLAEDIT_OT_move_down"; + ot->idname= "NLA_OT_move_down"; ot->description= "Move selected strips down a track if there's room."; /* api callbacks */ @@ -944,11 +944,11 @@ static int nlaedit_apply_scale_exec (bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void NLAEDIT_OT_apply_scale (wmOperatorType *ot) +void NLA_OT_apply_scale (wmOperatorType *ot) { /* identifiers */ ot->name= "Apply Scale"; - ot->idname= "NLAEDIT_OT_apply_scale"; + ot->idname= "NLA_OT_apply_scale"; ot->description= "Apply scaling of selected strips to their referenced Actions."; /* api callbacks */ @@ -1005,11 +1005,11 @@ static int nlaedit_clear_scale_exec (bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void NLAEDIT_OT_clear_scale (wmOperatorType *ot) +void NLA_OT_clear_scale (wmOperatorType *ot) { /* identifiers */ ot->name= "Clear Scale"; - ot->idname= "NLAEDIT_OT_clear_scale"; + ot->idname= "NLA_OT_clear_scale"; ot->description= "Reset scaling of selected strips."; /* api callbacks */ diff --git a/source/blender/editors/space_nla/nla_header.c b/source/blender/editors/space_nla/nla_header.c index 939e886abeb..fc6db76ba65 100644 --- a/source/blender/editors/space_nla/nla_header.c +++ b/source/blender/editors/space_nla/nla_header.c @@ -90,7 +90,7 @@ static void nla_viewmenu(bContext *C, uiLayout *layout, void *arg_unused) RNA_pointer_create(&sc->id, &RNA_SpaceNLA, snla, &spaceptr); /* create menu */ - uiItemO(layout, NULL, ICON_MENU_PANEL, "NLAEDIT_OT_properties"); + uiItemO(layout, NULL, ICON_MENU_PANEL, "NLA_OT_properties"); uiItemS(layout); @@ -104,9 +104,9 @@ static void nla_viewmenu(bContext *C, uiLayout *layout, void *arg_unused) uiItemS(layout); if (scene->flag & SCE_NLA_EDIT_ON) - uiItemO(layout, NULL, 0, "NLAEDIT_OT_tweakmode_exit"); + uiItemO(layout, NULL, 0, "NLA_OT_tweakmode_exit"); else - uiItemO(layout, NULL, 0, "NLAEDIT_OT_tweakmode_enter"); + uiItemO(layout, NULL, 0, "NLA_OT_tweakmode_enter"); uiItemS(layout); @@ -125,13 +125,13 @@ static void nla_viewmenu(bContext *C, uiLayout *layout, void *arg_unused) static void nla_selectmenu(bContext *C, uiLayout *layout, void *arg_unused) { - uiItemO(layout, NULL, 0, "NLAEDIT_OT_select_all_toggle"); - uiItemBooleanO(layout, "Invert All", 0, "NLAEDIT_OT_select_all_toggle", "invert", 1); + uiItemO(layout, NULL, 0, "NLA_OT_select_all_toggle"); + uiItemBooleanO(layout, "Invert All", 0, "NLA_OT_select_all_toggle", "invert", 1); uiItemS(layout); - uiItemO(layout, NULL, 0, "NLAEDIT_OT_select_border"); - uiItemBooleanO(layout, "Border Axis Range", 0, "NLAEDIT_OT_select_border", "axis_range", 1); + uiItemO(layout, NULL, 0, "NLA_OT_select_border"); + uiItemBooleanO(layout, "Border Axis Range", 0, "NLA_OT_select_border", "axis_range", 1); } static void nla_edit_transformmenu(bContext *C, uiLayout *layout, void *arg_unused) @@ -148,28 +148,28 @@ static void nla_editmenu(bContext *C, uiLayout *layout, void *arg_unused) uiItemS(layout); - uiItemO(layout, NULL, 0, "NLAEDIT_OT_duplicate"); - uiItemO(layout, NULL, 0, "NLAEDIT_OT_split"); + uiItemO(layout, NULL, 0, "NLA_OT_duplicate"); + uiItemO(layout, NULL, 0, "NLA_OT_split"); uiItemS(layout); - uiItemO(layout, NULL, 0, "NLAEDIT_OT_delete"); + uiItemO(layout, NULL, 0, "NLA_OT_delete"); uiItemS(layout); - uiItemO(layout, NULL, 0, "NLAEDIT_OT_apply_scale"); - uiItemO(layout, NULL, 0, "NLAEDIT_OT_clear_scale"); + uiItemO(layout, NULL, 0, "NLA_OT_apply_scale"); + uiItemO(layout, NULL, 0, "NLA_OT_clear_scale"); uiItemS(layout); - uiItemO(layout, NULL, 0, "NLAEDIT_OT_move_up"); - uiItemO(layout, NULL, 0, "NLAEDIT_OT_move_down"); + uiItemO(layout, NULL, 0, "NLA_OT_move_up"); + uiItemO(layout, NULL, 0, "NLA_OT_move_down"); } static void nla_addmenu(bContext *C, uiLayout *layout, void *arg_unused) { - uiItemO(layout, NULL, 0, "NLAEDIT_OT_add_actionclip"); - uiItemO(layout, NULL, 0, "NLAEDIT_OT_add_transition"); + uiItemO(layout, NULL, 0, "NLA_OT_add_actionclip"); + uiItemO(layout, NULL, 0, "NLA_OT_add_transition"); uiItemS(layout); diff --git a/source/blender/editors/space_nla/nla_intern.h b/source/blender/editors/space_nla/nla_intern.h index 7056139d734..f8df41d6225 100644 --- a/source/blender/editors/space_nla/nla_intern.h +++ b/source/blender/editors/space_nla/nla_intern.h @@ -54,7 +54,7 @@ ARegion *nla_has_buttons_region(ScrArea *sa); void nla_buttons_register(ARegionType *art); -void NLAEDIT_OT_properties(wmOperatorType *ot); +void NLA_OT_properties(wmOperatorType *ot); /* **************************************** */ /* nla_draw.c */ @@ -80,30 +80,30 @@ enum { /* --- */ -void NLAEDIT_OT_select_all_toggle(wmOperatorType *ot); -void NLAEDIT_OT_select_border(wmOperatorType *ot); -void NLAEDIT_OT_click_select(wmOperatorType *ot); +void NLA_OT_select_all_toggle(wmOperatorType *ot); +void NLA_OT_select_border(wmOperatorType *ot); +void NLA_OT_click_select(wmOperatorType *ot); /* **************************************** */ /* nla_edit.c */ -void NLAEDIT_OT_tweakmode_enter(wmOperatorType *ot); -void NLAEDIT_OT_tweakmode_exit(wmOperatorType *ot); +void NLA_OT_tweakmode_enter(wmOperatorType *ot); +void NLA_OT_tweakmode_exit(wmOperatorType *ot); /* --- */ -void NLAEDIT_OT_add_actionclip(wmOperatorType *ot); -void NLAEDIT_OT_add_transition(wmOperatorType *ot); +void NLA_OT_add_actionclip(wmOperatorType *ot); +void NLA_OT_add_transition(wmOperatorType *ot); -void NLAEDIT_OT_duplicate(wmOperatorType *ot); -void NLAEDIT_OT_delete(wmOperatorType *ot); -void NLAEDIT_OT_split(wmOperatorType *ot); +void NLA_OT_duplicate(wmOperatorType *ot); +void NLA_OT_delete(wmOperatorType *ot); +void NLA_OT_split(wmOperatorType *ot); -void NLAEDIT_OT_move_up(wmOperatorType *ot); -void NLAEDIT_OT_move_down(wmOperatorType *ot); +void NLA_OT_move_up(wmOperatorType *ot); +void NLA_OT_move_down(wmOperatorType *ot); -void NLAEDIT_OT_apply_scale(wmOperatorType *ot); -void NLAEDIT_OT_clear_scale(wmOperatorType *ot); +void NLA_OT_apply_scale(wmOperatorType *ot); +void NLA_OT_clear_scale(wmOperatorType *ot); /* **************************************** */ diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c index 35db79a0b38..d7bd894ce4d 100644 --- a/source/blender/editors/space_nla/nla_ops.c +++ b/source/blender/editors/space_nla/nla_ops.c @@ -126,7 +126,7 @@ short nlaedit_is_tweakmode_on (bAnimContext *ac) void nla_operatortypes(void) { /* view */ - WM_operatortype_append(NLAEDIT_OT_properties); + WM_operatortype_append(NLA_OT_properties); /* channels */ WM_operatortype_append(NLA_OT_channels_click); @@ -135,26 +135,26 @@ void nla_operatortypes(void) WM_operatortype_append(NLA_OT_delete_tracks); /* select */ - WM_operatortype_append(NLAEDIT_OT_click_select); - WM_operatortype_append(NLAEDIT_OT_select_border); - WM_operatortype_append(NLAEDIT_OT_select_all_toggle); + WM_operatortype_append(NLA_OT_click_select); + WM_operatortype_append(NLA_OT_select_border); + WM_operatortype_append(NLA_OT_select_all_toggle); /* edit */ - WM_operatortype_append(NLAEDIT_OT_tweakmode_enter); - WM_operatortype_append(NLAEDIT_OT_tweakmode_exit); + WM_operatortype_append(NLA_OT_tweakmode_enter); + WM_operatortype_append(NLA_OT_tweakmode_exit); - WM_operatortype_append(NLAEDIT_OT_add_actionclip); - WM_operatortype_append(NLAEDIT_OT_add_transition); + WM_operatortype_append(NLA_OT_add_actionclip); + WM_operatortype_append(NLA_OT_add_transition); - WM_operatortype_append(NLAEDIT_OT_duplicate); - WM_operatortype_append(NLAEDIT_OT_delete); - WM_operatortype_append(NLAEDIT_OT_split); + WM_operatortype_append(NLA_OT_duplicate); + WM_operatortype_append(NLA_OT_delete); + WM_operatortype_append(NLA_OT_split); - WM_operatortype_append(NLAEDIT_OT_move_up); - WM_operatortype_append(NLAEDIT_OT_move_down); + WM_operatortype_append(NLA_OT_move_up); + WM_operatortype_append(NLA_OT_move_down); - WM_operatortype_append(NLAEDIT_OT_apply_scale); - WM_operatortype_append(NLAEDIT_OT_clear_scale); + WM_operatortype_append(NLA_OT_apply_scale); + WM_operatortype_append(NLA_OT_clear_scale); } /* ************************** registration - keymaps **********************************/ @@ -208,19 +208,19 @@ static void nla_keymap_main (wmWindowManager *wm, ListBase *keymap) /* selection */ /* click select */ - WM_keymap_add_item(keymap, "NLAEDIT_OT_click_select", SELECTMOUSE, KM_PRESS, 0, 0); - kmi= WM_keymap_add_item(keymap, "NLAEDIT_OT_click_select", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0); + WM_keymap_add_item(keymap, "NLA_OT_click_select", SELECTMOUSE, KM_PRESS, 0, 0); + kmi= WM_keymap_add_item(keymap, "NLA_OT_click_select", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0); RNA_boolean_set(kmi->ptr, "extend", 1); - kmi= WM_keymap_add_item(keymap, "NLAEDIT_OT_click_select", SELECTMOUSE, KM_PRESS, KM_CTRL, 0); + kmi= WM_keymap_add_item(keymap, "NLA_OT_click_select", SELECTMOUSE, KM_PRESS, KM_CTRL, 0); RNA_enum_set(kmi->ptr, "left_right", NLAEDIT_LRSEL_TEST); /* deselect all */ - WM_keymap_add_item(keymap, "NLAEDIT_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0); - RNA_boolean_set(WM_keymap_add_item(keymap, "NLAEDIT_OT_select_all_toggle", IKEY, KM_PRESS, KM_CTRL, 0)->ptr, "invert", 1); + WM_keymap_add_item(keymap, "NLA_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0); + RNA_boolean_set(WM_keymap_add_item(keymap, "NLA_OT_select_all_toggle", IKEY, KM_PRESS, KM_CTRL, 0)->ptr, "invert", 1); /* borderselect */ - WM_keymap_add_item(keymap, "NLAEDIT_OT_select_border", BKEY, KM_PRESS, 0, 0); - RNA_boolean_set(WM_keymap_add_item(keymap, "NLAEDIT_OT_select_border", BKEY, KM_PRESS, KM_ALT, 0)->ptr, "axis_range", 1); + WM_keymap_add_item(keymap, "NLA_OT_select_border", BKEY, KM_PRESS, 0, 0); + RNA_boolean_set(WM_keymap_add_item(keymap, "NLA_OT_select_border", BKEY, KM_PRESS, KM_ALT, 0)->ptr, "axis_range", 1); /* editing */ @@ -228,32 +228,32 @@ static void nla_keymap_main (wmWindowManager *wm, ListBase *keymap) * - enter and exit are separate operators with the same hotkey... * This works as they use different poll()'s */ - WM_keymap_add_item(keymap, "NLAEDIT_OT_tweakmode_enter", TABKEY, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "NLAEDIT_OT_tweakmode_exit", TABKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "NLA_OT_tweakmode_enter", TABKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "NLA_OT_tweakmode_exit", TABKEY, KM_PRESS, 0, 0); /* add strips */ - WM_keymap_add_item(keymap, "NLAEDIT_OT_add_actionclip", AKEY, KM_PRESS, KM_SHIFT, 0); - WM_keymap_add_item(keymap, "NLAEDIT_OT_add_transition", TKEY, KM_PRESS, KM_SHIFT, 0); + WM_keymap_add_item(keymap, "NLA_OT_add_actionclip", AKEY, KM_PRESS, KM_SHIFT, 0); + WM_keymap_add_item(keymap, "NLA_OT_add_transition", TKEY, KM_PRESS, KM_SHIFT, 0); /* duplicate */ - WM_keymap_add_item(keymap, "NLAEDIT_OT_duplicate", DKEY, KM_PRESS, KM_SHIFT, 0); + WM_keymap_add_item(keymap, "NLA_OT_duplicate", DKEY, KM_PRESS, KM_SHIFT, 0); /* delete */ - WM_keymap_add_item(keymap, "NLAEDIT_OT_delete", XKEY, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "NLAEDIT_OT_delete", DELKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "NLA_OT_delete", XKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "NLA_OT_delete", DELKEY, KM_PRESS, 0, 0); /* split */ - WM_keymap_add_item(keymap, "NLAEDIT_OT_split", YKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "NLA_OT_split", YKEY, KM_PRESS, 0, 0); /* move up */ - WM_keymap_add_item(keymap, "NLAEDIT_OT_move_up", PAGEUPKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "NLA_OT_move_up", PAGEUPKEY, KM_PRESS, 0, 0); /* move down */ - WM_keymap_add_item(keymap, "NLAEDIT_OT_move_down", PAGEDOWNKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "NLA_OT_move_down", PAGEDOWNKEY, KM_PRESS, 0, 0); /* apply scale */ - WM_keymap_add_item(keymap, "NLAEDIT_OT_apply_scale", AKEY, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "NLA_OT_apply_scale", AKEY, KM_PRESS, KM_CTRL, 0); /* clear scale */ - WM_keymap_add_item(keymap, "NLAEDIT_OT_clear_scale", SKEY, KM_PRESS, KM_ALT, 0); + WM_keymap_add_item(keymap, "NLA_OT_clear_scale", SKEY, KM_PRESS, KM_ALT, 0); /* transform system */ transform_keymap_for_space(wm, keymap, SPACE_NLA); @@ -267,7 +267,7 @@ void nla_keymap(wmWindowManager *wm) /* keymap for all regions */ keymap= WM_keymap_listbase(wm, "NLA Generic", SPACE_NLA, 0); - WM_keymap_add_item(keymap, "NLAEDIT_OT_properties", NKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "NLA_OT_properties", NKEY, KM_PRESS, 0, 0); /* channels */ /* Channels are not directly handled by the NLA Editor module, but are inherited from the Animation module. diff --git a/source/blender/editors/space_nla/nla_select.c b/source/blender/editors/space_nla/nla_select.c index 28027d0d9cd..c238818dd1e 100644 --- a/source/blender/editors/space_nla/nla_select.c +++ b/source/blender/editors/space_nla/nla_select.c @@ -191,11 +191,11 @@ static int nlaedit_deselectall_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void NLAEDIT_OT_select_all_toggle (wmOperatorType *ot) +void NLA_OT_select_all_toggle (wmOperatorType *ot) { /* identifiers */ ot->name= "Select All"; - ot->idname= "NLAEDIT_OT_select_all_toggle"; + ot->idname= "NLA_OT_select_all_toggle"; /* api callbacks */ ot->exec= nlaedit_deselectall_exec; @@ -327,11 +327,11 @@ static int nlaedit_borderselect_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void NLAEDIT_OT_select_border(wmOperatorType *ot) +void NLA_OT_select_border(wmOperatorType *ot) { /* identifiers */ ot->name= "Border Select"; - ot->idname= "NLAEDIT_OT_select_border"; + ot->idname= "NLA_OT_select_border"; /* api callbacks */ ot->invoke= WM_border_select_invoke; @@ -434,7 +434,7 @@ static void mouse_nla_strips (bContext *C, bAnimContext *ac, int mval[2], short * now that we've found our target... */ if (scene->flag & SCE_NLA_EDIT_ON) - WM_operator_name_call(C, "NLAEDIT_OT_tweakmode_exit", WM_OP_EXEC_DEFAULT, NULL); + WM_operator_name_call(C, "NLA_OT_tweakmode_exit", WM_OP_EXEC_DEFAULT, NULL); /* for replacing selection, firstly need to clear existing selection */ if (select_mode == SELECT_REPLACE) { @@ -488,7 +488,7 @@ static void nlaedit_mselect_leftright (bContext *C, bAnimContext *ac, short left /* if currently in tweakmode, exit tweakmode first */ if (scene->flag & SCE_NLA_EDIT_ON) - WM_operator_name_call(C, "NLAEDIT_OT_tweakmode_exit", WM_OP_EXEC_DEFAULT, NULL); + WM_operator_name_call(C, "NLA_OT_tweakmode_exit", WM_OP_EXEC_DEFAULT, NULL); /* if select mode is replace, deselect all keyframes (and channels) first */ if (select_mode==SELECT_REPLACE) { @@ -589,11 +589,11 @@ static int nlaedit_clickselect_invoke(bContext *C, wmOperator *op, wmEvent *even return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH; } -void NLAEDIT_OT_click_select (wmOperatorType *ot) +void NLA_OT_click_select (wmOperatorType *ot) { /* identifiers */ ot->name= "Mouse Select"; - ot->idname= "NLAEDIT_OT_click_select"; + ot->idname= "NLA_OT_click_select"; /* api callbacks - absolutely no exec() this yet... */ ot->invoke= nlaedit_clickselect_invoke; From aa4ed13e4a216a3464f7b9d6643c195927aea98a Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sun, 28 Jun 2009 07:32:00 +0000 Subject: [PATCH 068/114] NLA SoC: NLA Mapping Cleanup While trying to fix the mapping conversions for repeat, I came across some limitations with the current (soon to be previous) mapping methods. Now the mapping conversions should work nicely for all places that use them. --- source/blender/blenkernel/BKE_nla.h | 17 +++++- source/blender/blenkernel/intern/anim_sys.c | 2 +- source/blender/blenkernel/intern/nla.c | 59 ++++++++++++------- source/blender/blenkernel/nla_private.h | 3 +- source/blender/editors/animation/anim_draw.c | 16 ++--- .../editors/space_action/action_edit.c | 6 +- .../editors/space_action/action_select.c | 12 ++-- .../blender/editors/space_graph/graph_edit.c | 8 +-- .../editors/space_graph/graph_select.c | 8 +-- source/blender/editors/space_nla/nla_edit.c | 6 +- .../editors/space_view3d/drawarmature.c | 4 +- source/blender/editors/transform/transform.c | 16 ++--- .../editors/transform/transform_conversions.c | 14 ++--- 13 files changed, 103 insertions(+), 68 deletions(-) diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index cc73ac02690..e2b1dd89deb 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -73,7 +73,22 @@ void BKE_nla_action_pushdown(struct AnimData *adt); short BKE_nla_tweakmode_enter(struct AnimData *adt); void BKE_nla_tweakmode_exit(struct AnimData *adt); -float BKE_nla_tweakedit_remap(struct AnimData *adt, float cframe, short invert); +/* ----------------------------- */ +/* Time Mapping */ + +/* time mapping conversion modes */ +enum { + /* convert from global time to strip time - for evaluation */ + NLATIME_CONVERT_EVAL = 0, + /* convert from global time to strip time - for editing corrections */ + // XXX old 0 invert + NLATIME_CONVERT_UNMAP, + /* convert from strip time to global time */ + // xxx old 1 invert + NLATIME_CONVERT_MAP, +} eNlaTime_ConvertModes; + +float BKE_nla_tweakedit_remap(struct AnimData *adt, float cframe, short mode); #endif diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 288867505be..4c0c30fe5c1 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -604,7 +604,7 @@ static void nlastrip_evaluate_controls (NlaStrip *strip, float ctime) { /* firstly, analytically generate values for influence and time (if applicable) */ if ((strip->flag & NLASTRIP_FLAG_USR_TIME) == 0) - strip->strip_time= nlastrip_get_frame(strip, ctime, 0); + strip->strip_time= nlastrip_get_frame(strip, ctime, NLATIME_CONVERT_EVAL); if ((strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) == 0) strip->influence= nlastrip_get_influence(strip, ctime); diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 760139bee15..2b95584dc25 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -329,7 +329,7 @@ NlaStrip *add_nlastrip_to_stack (AnimData *adt, bAction *act) /* non clipped mapping for strip-time <-> global time (for Action-Clips) * invert = convert action-strip time to global time */ -static float nlastrip_get_frame_actionclip (NlaStrip *strip, float cframe, short invert) +static float nlastrip_get_frame_actionclip (NlaStrip *strip, float cframe, short mode) { float actlength, repeat, scale; @@ -347,9 +347,20 @@ static float nlastrip_get_frame_actionclip (NlaStrip *strip, float cframe, short /* reversed = play strip backwards */ if (strip->flag & NLASTRIP_FLAG_REVERSE) { - /* invert = convert action-strip time to global time */ - if (invert) - return scale*(strip->actend - cframe) + strip->start; // FIXME: this doesn't work for multiple repeats yet + // FIXME: this won't work right with Graph Editor? + if (mode == NLATIME_CONVERT_MAP) { + return strip->end - scale*(cframe - strip->actstart); + } + else if (mode == NLATIME_CONVERT_UNMAP) { + int repeatsNum = (int)((cframe - strip->start) / (actlength * scale)); + + /* this method doesn't clip the values to lie within the action range only + * - the '(repeatsNum * actlength * scale)' compensates for the fmod(...) + * - the fmod(...) works in the same way as for eval + */ + return strip->actend - (repeatsNum * actlength * scale) + - (fmod(cframe - strip->start, actlength*scale) / scale); + } else { if (IS_EQ(cframe, strip->end) && IS_EQ(strip->repeat, ((int)strip->repeat))) { /* this case prevents the motion snapping back to the first frame at the end of the strip @@ -367,10 +378,20 @@ static float nlastrip_get_frame_actionclip (NlaStrip *strip, float cframe, short } } else { - /* invert = convert action-strip time to global time */ - if (invert) - return scale*(cframe - strip->actstart) + strip->start; // FIXME: this doesn't work for mutiple repeats yet - else { + if (mode == NLATIME_CONVERT_MAP) { + return strip->start + scale*(cframe - strip->actstart); + } + else if (mode == NLATIME_CONVERT_UNMAP) { + int repeatsNum = (int)((cframe - strip->start) / (actlength * scale)); + + /* this method doesn't clip the values to lie within the action range only + * - the '(repeatsNum * actlength * scale)' compensates for the fmod(...) + * - the fmod(...) works in the same way as for eval + */ + return strip->actstart + (repeatsNum * actlength * scale) + + (fmod(cframe - strip->start, actlength*scale) / scale); + } + else /* if (mode == NLATIME_CONVERT_EVAL) */{ if (IS_EQ(cframe, strip->end) && IS_EQ(strip->repeat, ((int)strip->repeat))) { /* this case prevents the motion snapping back to the first frame at the end of the strip * by catching the case where repeats is a whole number, which means that the end of the strip @@ -391,7 +412,7 @@ static float nlastrip_get_frame_actionclip (NlaStrip *strip, float cframe, short /* non clipped mapping for strip-time <-> global time (for Transitions) * invert = convert action-strip time to global time */ -static float nlastrip_get_frame_transition (NlaStrip *strip, float cframe, short invert) +static float nlastrip_get_frame_transition (NlaStrip *strip, float cframe, short mode) { float length; @@ -400,15 +421,13 @@ static float nlastrip_get_frame_transition (NlaStrip *strip, float cframe, short /* reversed = play strip backwards */ if (strip->flag & NLASTRIP_FLAG_REVERSE) { - /* invert = convert within-strip-time to global time */ - if (invert) + if (mode == NLATIME_CONVERT_MAP) return strip->end - (length * cframe); else return (strip->end - cframe) / length; } else { - /* invert = convert within-strip-time to global time */ - if (invert) + if (mode == NLATIME_CONVERT_MAP) return (length * cframe) + strip->start; else return (cframe - strip->start) / length; @@ -416,31 +435,31 @@ static float nlastrip_get_frame_transition (NlaStrip *strip, float cframe, short } /* non clipped mapping for strip-time <-> global time - * invert = convert action-strip time to global time + * mode = eNlaTime_ConvertModes[] -> NLATIME_CONVERT_* * * only secure for 'internal' (i.e. within AnimSys evaluation) operations, * but should not be directly relied on for stuff which interacts with editors */ -float nlastrip_get_frame (NlaStrip *strip, float cframe, short invert) +float nlastrip_get_frame (NlaStrip *strip, float cframe, short mode) { switch (strip->type) { case NLASTRIP_TYPE_TRANSITION: /* transition */ - return nlastrip_get_frame_transition(strip, cframe, invert); + return nlastrip_get_frame_transition(strip, cframe, mode); case NLASTRIP_TYPE_CLIP: /* action-clip (default) */ default: - return nlastrip_get_frame_actionclip(strip, cframe, invert); + return nlastrip_get_frame_actionclip(strip, cframe, mode); } } /* Non clipped mapping for strip-time <-> global time - * invert = convert strip-time to global time + * mode = eNlaTime_ConvertModesp[] -> NLATIME_CONVERT_* * * Public API method - perform this mapping using the given AnimData block * and perform any necessary sanity checks on the value */ -float BKE_nla_tweakedit_remap (AnimData *adt, float cframe, short invert) +float BKE_nla_tweakedit_remap (AnimData *adt, float cframe, short mode) { NlaStrip *strip; @@ -469,7 +488,7 @@ float BKE_nla_tweakedit_remap (AnimData *adt, float cframe, short invert) return cframe; /* perform the correction now... */ - return nlastrip_get_frame(strip, cframe, invert); + return nlastrip_get_frame(strip, cframe, mode); } /* *************************************************** */ diff --git a/source/blender/blenkernel/nla_private.h b/source/blender/blenkernel/nla_private.h index af886fb7de8..1514a79f03b 100644 --- a/source/blender/blenkernel/nla_private.h +++ b/source/blender/blenkernel/nla_private.h @@ -73,6 +73,7 @@ typedef struct NlaEvalChannel { /* --------------- NLA Functions (not to be used as a proper API) ----------------------- */ /* convert from strip time <-> global time */ -float nlastrip_get_frame(NlaStrip *strip, float cframe, short invert); +float nlastrip_get_frame(NlaStrip *strip, float cframe, short mode); + #endif // NLA_PRIVATE diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c index 6d079fe148a..f7702379645 100644 --- a/source/blender/editors/animation/anim_draw.c +++ b/source/blender/editors/animation/anim_draw.c @@ -270,8 +270,8 @@ void ANIM_nla_mapping_draw(gla2DDrawInfo *di, AnimData *adt, short restore) gla2DGetMap(di, &stored); map= stored; - map.xmin= BKE_nla_tweakedit_remap(adt, map.xmin, 0); - map.xmax= BKE_nla_tweakedit_remap(adt, map.xmax, 0); + map.xmin= BKE_nla_tweakedit_remap(adt, map.xmin, NLATIME_CONVERT_MAP); + map.xmax= BKE_nla_tweakedit_remap(adt, map.xmax, NLATIME_CONVERT_MAP); if (map.xmin == map.xmax) map.xmax += 1.0f; gla2DSetMap(di, &map); @@ -289,11 +289,11 @@ static short bezt_nlamapping_restore(BeztEditData *bed, BezTriple *bezt) /* adjust BezTriple handles only if allowed to */ if (only_keys == 0) { - bezt->vec[0][0]= BKE_nla_tweakedit_remap(adt, bezt->vec[0][0], 0); - bezt->vec[2][0]= BKE_nla_tweakedit_remap(adt, bezt->vec[2][0], 0); + bezt->vec[0][0]= BKE_nla_tweakedit_remap(adt, bezt->vec[0][0], NLATIME_CONVERT_UNMAP); + bezt->vec[2][0]= BKE_nla_tweakedit_remap(adt, bezt->vec[2][0], NLATIME_CONVERT_UNMAP); } - bezt->vec[1][0]= BKE_nla_tweakedit_remap(adt, bezt->vec[1][0], 0); + bezt->vec[1][0]= BKE_nla_tweakedit_remap(adt, bezt->vec[1][0], NLATIME_CONVERT_UNMAP); return 0; } @@ -307,11 +307,11 @@ static short bezt_nlamapping_apply(BeztEditData *bed, BezTriple *bezt) /* adjust BezTriple handles only if allowed to */ if (only_keys == 0) { - bezt->vec[0][0]= BKE_nla_tweakedit_remap(adt, bezt->vec[0][0], 1); - bezt->vec[2][0]= BKE_nla_tweakedit_remap(adt, bezt->vec[2][0], 1); + bezt->vec[0][0]= BKE_nla_tweakedit_remap(adt, bezt->vec[0][0], NLATIME_CONVERT_MAP); + bezt->vec[2][0]= BKE_nla_tweakedit_remap(adt, bezt->vec[2][0], NLATIME_CONVERT_MAP); } - bezt->vec[1][0]= BKE_nla_tweakedit_remap(adt, bezt->vec[1][0], 1); + bezt->vec[1][0]= BKE_nla_tweakedit_remap(adt, bezt->vec[1][0], NLATIME_CONVERT_MAP); return 0; } diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index 61dbc41e7c8..dd351c92cf2 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -121,8 +121,8 @@ static void get_keyframe_extents (bAnimContext *ac, float *min, float *max) calc_fcurve_range(fcu, &tmin, &tmax); if (adt) { - tmin= BKE_nla_tweakedit_remap(adt, tmin, 1); - tmax= BKE_nla_tweakedit_remap(adt, tmax, 1); + tmin= BKE_nla_tweakedit_remap(adt, tmin, NLATIME_CONVERT_MAP); + tmax= BKE_nla_tweakedit_remap(adt, tmax, NLATIME_CONVERT_MAP); } /* try to set cur using these values, if they're more extreme than previously set values */ @@ -406,7 +406,7 @@ static void insert_action_keys(bAnimContext *ac, short mode) /* adjust current frame for NLA-scaling */ if (adt) - cfra= BKE_nla_tweakedit_remap(adt, (float)CFRA, 0); + cfra= BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); else cfra= (float)CFRA; diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c index 451d120ff9b..d45e32dd3bb 100644 --- a/source/blender/editors/space_action/action_select.c +++ b/source/blender/editors/space_action/action_select.c @@ -255,8 +255,8 @@ static void borderselect_action (bAnimContext *ac, rcti rect, short mode, short if (ELEM(mode, ACTKEYS_BORDERSEL_FRAMERANGE, ACTKEYS_BORDERSEL_ALLKEYS)) { /* if channel is mapped in NLA, apply correction */ if (adt) { - bed.f1= BKE_nla_tweakedit_remap(adt, rectf.xmin, 0); - bed.f2= BKE_nla_tweakedit_remap(adt, rectf.xmax, 0); + bed.f1= BKE_nla_tweakedit_remap(adt, rectf.xmin, NLATIME_CONVERT_UNMAP); + bed.f2= BKE_nla_tweakedit_remap(adt, rectf.xmax, NLATIME_CONVERT_UNMAP); } else { bed.f1= rectf.xmin; @@ -504,7 +504,7 @@ static void columnselect_action_keys (bAnimContext *ac, short mode) for (ce= bed.list.first; ce; ce= ce->next) { /* set frame for validation callback to refer to */ if (adt) - bed.f1= BKE_nla_tweakedit_remap(adt, ce->cfra, 0); + bed.f1= BKE_nla_tweakedit_remap(adt, ce->cfra, NLATIME_CONVERT_UNMAP); else bed.f1= ce->cfra; @@ -707,7 +707,7 @@ static void actkeys_mselect_column(bAnimContext *ac, short select_mode, float se /* set frame for validation callback to refer to */ if (adt) - bed.f1= BKE_nla_tweakedit_remap(adt, selx, 0); + bed.f1= BKE_nla_tweakedit_remap(adt, selx, NLATIME_CONVERT_UNMAP); else bed.f1= selx; @@ -779,8 +779,8 @@ static void mouse_action_keys (bAnimContext *ac, int mval[2], short select_mode, /* apply NLA-scaling correction? */ if (adt) { - xmin= BKE_nla_tweakedit_remap(adt, rectf.xmin, 0); - xmax= BKE_nla_tweakedit_remap(adt, rectf.xmax, 0); + xmin= BKE_nla_tweakedit_remap(adt, rectf.xmin, NLATIME_CONVERT_UNMAP); + xmax= BKE_nla_tweakedit_remap(adt, rectf.xmax, NLATIME_CONVERT_UNMAP); } else { xmin= rectf.xmin; diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index fc04308077c..e38c24ed223 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -123,8 +123,8 @@ static void get_graph_keyframe_extents (bAnimContext *ac, float *xmin, float *xm calc_fcurve_bounds(fcu, &txmin, &txmax, &tymin, &tymax); if (adt) { - txmin= BKE_nla_tweakedit_remap(adt, txmin, 1); - txmax= BKE_nla_tweakedit_remap(adt, txmax, 1); + txmin= BKE_nla_tweakedit_remap(adt, txmin, NLATIME_CONVERT_MAP); + txmax= BKE_nla_tweakedit_remap(adt, txmax, NLATIME_CONVERT_MAP); } /* try to set cur using these values, if they're more extreme than previously set values */ @@ -288,7 +288,7 @@ static void create_ghost_curves (bAnimContext *ac, int start, int end) /* use the sampling callback at 1-frame intervals from start to end frames */ for (cfra= start; cfra <= end; cfra++, fpt++) { - float cfrae= BKE_nla_tweakedit_remap(adt, cfra, 0); + float cfrae= BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP); fpt->vec[0]= cfrae; fpt->vec[1]= fcurve_samplingcb_evalcurve(fcu, NULL, cfrae); @@ -427,7 +427,7 @@ static int graphkeys_click_insert_exec (bContext *C, wmOperator *op) /* apply inverse NLA-mapping to frame to get correct time in un-scaled action */ adt= ANIM_nla_mapping_get(&ac, ale); - frame= BKE_nla_tweakedit_remap(adt, frame, 0); + frame= BKE_nla_tweakedit_remap(adt, frame, NLATIME_CONVERT_UNMAP); /* insert keyframe on the specified frame + value */ insert_vert_fcurve((FCurve *)ale->data, frame, val, 0); diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c index d600396fd77..afe66ed179e 100644 --- a/source/blender/editors/space_graph/graph_select.c +++ b/source/blender/editors/space_graph/graph_select.c @@ -238,8 +238,8 @@ static void borderselect_graphkeys (bAnimContext *ac, rcti rect, short mode, sho if (mode != BEZT_OK_VALUERANGE) { /* if channel is mapped in NLA, apply correction */ if (adt) { - bed.f1= BKE_nla_tweakedit_remap(adt, rectf.xmin, 0); - bed.f2= BKE_nla_tweakedit_remap(adt, rectf.xmax, 0); + bed.f1= BKE_nla_tweakedit_remap(adt, rectf.xmin, NLATIME_CONVERT_UNMAP); + bed.f2= BKE_nla_tweakedit_remap(adt, rectf.xmax, NLATIME_CONVERT_UNMAP); } else { bed.f1= rectf.xmin; @@ -459,7 +459,7 @@ static void columnselect_graph_keys (bAnimContext *ac, short mode) for (ce= bed.list.first; ce; ce= ce->next) { /* set frame for validation callback to refer to */ if (ale) - bed.f1= BKE_nla_tweakedit_remap(adt, ce->cfra, 0); + bed.f1= BKE_nla_tweakedit_remap(adt, ce->cfra, NLATIME_CONVERT_UNMAP); else bed.f1= ce->cfra; @@ -841,7 +841,7 @@ static void graphkeys_mselect_column (bAnimContext *ac, int mval[2], short selec /* set frame for validation callback to refer to */ if (adt) - bed.f1= BKE_nla_tweakedit_remap(adt, selx, 0); + bed.f1= BKE_nla_tweakedit_remap(adt, selx, NLATIME_CONVERT_UNMAP); else bed.f1= selx; diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index bcf3bd4746a..6d82e3d4be2 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -870,9 +870,9 @@ static short bezt_apply_nlamapping (BeztEditData *bed, BezTriple *bezt) NlaStrip *strip= (NlaStrip *)bed->data; /* adjust all the times */ - bezt->vec[0][0]= nlastrip_get_frame(strip, bezt->vec[0][0], 1); - bezt->vec[1][0]= nlastrip_get_frame(strip, bezt->vec[1][0], 1); - bezt->vec[2][0]= nlastrip_get_frame(strip, bezt->vec[2][0], 1); + bezt->vec[0][0]= nlastrip_get_frame(strip, bezt->vec[0][0], NLATIME_CONVERT_MAP); + bezt->vec[1][0]= nlastrip_get_frame(strip, bezt->vec[1][0], NLATIME_CONVERT_MAP); + bezt->vec[2][0]= nlastrip_get_frame(strip, bezt->vec[2][0], NLATIME_CONVERT_MAP); /* nothing to return or else we exit */ return 0; diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c index a4332ea1709..0827bcaa9ae 100644 --- a/source/blender/editors/space_view3d/drawarmature.c +++ b/source/blender/editors/space_view3d/drawarmature.c @@ -2434,7 +2434,7 @@ static void draw_ghost_poses(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base /* only within action range */ if (actframe+ctime >= start && actframe+ctime <= end) { - CFRA= (int)BKE_nla_tweakedit_remap(adt, actframe+ctime, 1); + CFRA= (int)BKE_nla_tweakedit_remap(adt, actframe+ctime, NLATIME_CONVERT_MAP); if (CFRA != cfrao) { BKE_animsys_evaluate_animdata(&ob->id, adt, (float)CFRA, ADT_RECALC_ALL); @@ -2449,7 +2449,7 @@ static void draw_ghost_poses(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base /* only within action range */ if ((actframe-ctime >= start) && (actframe-ctime <= end)) { - CFRA= (int)BKE_nla_tweakedit_remap(adt, actframe-ctime, 1); + CFRA= (int)BKE_nla_tweakedit_remap(adt, actframe-ctime, NLATIME_CONVERT_MAP); if (CFRA != cfrao) { BKE_animsys_evaluate_animdata(&ob->id, adt, (float)CFRA, ADT_RECALC_ALL); diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index ded6edbbb0e..9d8371afd61 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -4365,7 +4365,7 @@ static void doAnimEdit_SnapFrame(TransInfo *t, TransData *td, AnimData *adt, sho /* convert frame to nla-action time (if needed) */ if (adt) - val= BKE_nla_tweakedit_remap(adt, *(td->val), 1); + val= BKE_nla_tweakedit_remap(adt, *(td->val), NLATIME_CONVERT_MAP); else val= *(td->val); @@ -4377,7 +4377,7 @@ static void doAnimEdit_SnapFrame(TransInfo *t, TransData *td, AnimData *adt, sho /* convert frame out of nla-action time */ if (adt) - *(td->val)= BKE_nla_tweakedit_remap(adt, val, 0); + *(td->val)= BKE_nla_tweakedit_remap(adt, val, NLATIME_CONVERT_UNMAP); else *(td->val)= val; } @@ -4387,7 +4387,7 @@ static void doAnimEdit_SnapFrame(TransInfo *t, TransData *td, AnimData *adt, sho /* convert frame to nla-action time (if needed) */ if (adt) - val= BKE_nla_tweakedit_remap(adt, *(td->val), 1); + val= BKE_nla_tweakedit_remap(adt, *(td->val), NLATIME_CONVERT_MAP); else val= *(td->val); @@ -4397,7 +4397,7 @@ static void doAnimEdit_SnapFrame(TransInfo *t, TransData *td, AnimData *adt, sho /* convert frame out of nla-action time */ if (adt) - *(td->val)= BKE_nla_tweakedit_remap(adt, val, 0); + *(td->val)= BKE_nla_tweakedit_remap(adt, val, NLATIME_CONVERT_UNMAP); else *(td->val)= val; } @@ -4487,9 +4487,9 @@ static void applyTimeTranslate(TransInfo *t, float sval) deltax= (float)( floor(deltax + 0.5f) ); } - val = BKE_nla_tweakedit_remap(adt, td->ival, 1); + val = BKE_nla_tweakedit_remap(adt, td->ival, NLATIME_CONVERT_MAP); val += deltax; - *(td->val) = BKE_nla_tweakedit_remap(adt, val, 0); + *(td->val) = BKE_nla_tweakedit_remap(adt, val, NLATIME_CONVERT_UNMAP); } else { deltax = val = t->values[0]; @@ -4614,7 +4614,7 @@ static void applyTimeSlide(TransInfo *t, float sval) /* apply NLA-mapping to necessary values */ if (adt) - cval= BKE_nla_tweakedit_remap(adt, cval, 0); + cval= BKE_nla_tweakedit_remap(adt, cval, NLATIME_CONVERT_UNMAP); /* only apply to data if in range */ if ((sval > minx) && (sval < maxx)) { @@ -4726,7 +4726,7 @@ static void applyTimeScale(TransInfo *t) { /* check if any need to apply nla-mapping */ if (adt) - startx= BKE_nla_tweakedit_remap(adt, startx, 0); + startx= BKE_nla_tweakedit_remap(adt, startx, NLATIME_CONVERT_UNMAP); /* now, calculate the new value */ *(td->val) = td->ival - startx; diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index d23f8fdfe40..b2afaac23de 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -3080,7 +3080,7 @@ static void createTransActionData(bContext *C, TransInfo *t) * higher scaling ratios, but is faster than converting all points) */ if (adt) - cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, 0); + cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); else cfra = (float)CFRA; @@ -3134,7 +3134,7 @@ static void createTransActionData(bContext *C, TransInfo *t) * higher scaling ratios, but is faster than converting all points) */ if (adt) - cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, 0); + cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); else cfra = (float)CFRA; @@ -3180,13 +3180,13 @@ static void bezt_to_transdata (TransData *td, TransData2D *td2d, AnimData *adt, */ if (adt) { - td2d->loc[0] = BKE_nla_tweakedit_remap(adt, loc[0], 0); + td2d->loc[0] = BKE_nla_tweakedit_remap(adt, loc[0], NLATIME_CONVERT_UNMAP); td2d->loc[1] = loc[1]; td2d->loc[2] = 0.0f; td2d->loc2d = loc; td->loc = td2d->loc; - td->center[0] = BKE_nla_tweakedit_remap(adt, cent[0], 0); + td->center[0] = BKE_nla_tweakedit_remap(adt, cent[0], NLATIME_CONVERT_UNMAP); td->center[1] = cent[1]; td->center[2] = 0.0f; @@ -3277,7 +3277,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) * higher scaling ratios, but is faster than converting all points) */ if (adt) - cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, 0); + cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); else cfra = (float)CFRA; @@ -3336,7 +3336,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) * higher scaling ratios, but is faster than converting all points) */ if (adt) - cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, 0); + cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); else cfra = (float)CFRA; @@ -3622,7 +3622,7 @@ void flushTransGraphData(TransInfo *t) /* we need to unapply the nla-scaling from the time in some situations */ if (adt) - td2d->loc2d[0]= BKE_nla_tweakedit_remap(adt, td2d->loc[0], 0); + td2d->loc2d[0]= BKE_nla_tweakedit_remap(adt, td2d->loc[0], NLATIME_CONVERT_UNMAP); else td2d->loc2d[0]= td2d->loc[0]; From 26c7c01c32957f17a3f6cffb52975eddc7cd40f1 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Mon, 29 Jun 2009 01:00:35 +0000 Subject: [PATCH 069/114] NLA SoC: Lines are now drawn on action-clip strips for indicating the timing of repeats --- source/blender/editors/space_nla/nla_draw.c | 17 +++++++++++++++++ source/blender/makesrna/intern/rna_nla.c | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index 51c1960c4c6..6d4f65fe249 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -293,6 +293,23 @@ static void nla_draw_strip (AnimData *adt, NlaTrack *nlt, NlaStrip *strip, View2 /* draw outline */ gl_round_box_shade(GL_LINE_LOOP, strip->start, yminc, strip->end, ymaxc, 0.0, 0.0, 0.1); + /* if action-clip strip, draw lines delimiting repeats too (in the same colour */ + if ((strip->type == NLASTRIP_TYPE_CLIP) && IS_EQ(strip->repeat, 1.0f)==0) { + float repeatLen = (strip->actend - strip->actstart) * strip->scale; + int i; + + /* only draw lines for whole-numbered repeats, starting from the first full-repeat + * up to the last full repeat (but not if it lies on the end of the strip) + */ + for (i = 1; i < strip->repeat; i++) { + float repeatPos = strip->start + (repeatLen * i); + + /* don't draw if line would end up on or after the end of the strip */ + if (repeatPos < strip->end) + fdrawline(repeatPos, yminc, repeatPos, ymaxc); + } + } + /* reset linestyle */ setlinestyle(0); } diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c index 5dc624b67bc..965692212a5 100644 --- a/source/blender/makesrna/intern/rna_nla.c +++ b/source/blender/makesrna/intern/rna_nla.c @@ -288,7 +288,7 @@ void rna_def_nlastrip(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "repeat"); RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_repeat_set", NULL); RNA_def_property_range(prop, 0.1f, 1000.0f); /* these limits have currently be chosen arbitarily, but could be extended (minimum should still be > 0 though) if needed... */ - RNA_def_property_ui_text(prop, "Repeat", "Number of times to repeat the "); + RNA_def_property_ui_text(prop, "Repeat", "Number of times to repeat the action range."); prop= RNA_def_property(srna, "scale", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "scale"); From 2c3e8850a53020310a6a8f5c51b764ca261c24c0 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Mon, 29 Jun 2009 03:02:41 +0000 Subject: [PATCH 070/114] NLA SoC: Insert Keyframe Operator Tweaks (Anim Editor Versions) * Insert Keyframe (IKEY) operator for Graph Editor * Renamed the DopeSheet version to make it more consistent with the other keyframing operators --- .../editors/space_action/action_edit.c | 8 +- .../editors/space_action/action_header.c | 2 +- .../editors/space_action/action_intern.h | 2 +- .../blender/editors/space_action/action_ops.c | 4 +- .../blender/editors/space_graph/graph_edit.c | 98 ++++++++++++++++++- .../editors/space_graph/graph_header.c | 2 +- .../editors/space_graph/graph_intern.h | 1 + .../blender/editors/space_graph/graph_ops.c | 2 + 8 files changed, 109 insertions(+), 10 deletions(-) diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index dd351c92cf2..505ff18d7bd 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -433,10 +433,10 @@ static int actkeys_insertkey_exec(bContext *C, wmOperator *op) if (ac.datatype == ANIMCONT_GPENCIL) return OPERATOR_CANCELLED; - /* get snapping mode */ + /* what channels to affect? */ mode= RNA_enum_get(op->ptr, "type"); - /* snap keyframes */ + /* insert keyframes */ insert_action_keys(&ac, mode); /* validate keyframes after editing */ @@ -448,11 +448,11 @@ static int actkeys_insertkey_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void ACT_OT_insert (wmOperatorType *ot) +void ACT_OT_insert_keyframe (wmOperatorType *ot) { /* identifiers */ ot->name= "Insert Keyframes"; - ot->idname= "ACT_OT_insert"; + ot->idname= "ACT_OT_insert_keyframe"; /* api callbacks */ ot->invoke= WM_menu_invoke; diff --git a/source/blender/editors/space_action/action_header.c b/source/blender/editors/space_action/action_header.c index 62e7a2d8e3f..b2614411002 100644 --- a/source/blender/editors/space_action/action_header.c +++ b/source/blender/editors/space_action/action_header.c @@ -211,7 +211,7 @@ static void act_editmenu(bContext *C, uiLayout *layout, void *arg_unused) uiItemS(layout); - uiItemO(layout, NULL, 0, "ACT_OT_insert"); + uiItemO(layout, NULL, 0, "ACT_OT_insert_keyframe"); uiItemS(layout); diff --git a/source/blender/editors/space_action/action_intern.h b/source/blender/editors/space_action/action_intern.h index 6ccdc07421b..26655892176 100644 --- a/source/blender/editors/space_action/action_intern.h +++ b/source/blender/editors/space_action/action_intern.h @@ -83,7 +83,7 @@ void ACT_OT_view_all(struct wmOperatorType *ot); void ACT_OT_copy(struct wmOperatorType *ot); void ACT_OT_paste(struct wmOperatorType *ot); -void ACT_OT_insert(struct wmOperatorType *ot); +void ACT_OT_insert_keyframe(struct wmOperatorType *ot); void ACT_OT_duplicate(struct wmOperatorType *ot); void ACT_OT_delete(struct wmOperatorType *ot); void ACT_OT_clean(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_action/action_ops.c b/source/blender/editors/space_action/action_ops.c index c023062453c..674506ddba0 100644 --- a/source/blender/editors/space_action/action_ops.c +++ b/source/blender/editors/space_action/action_ops.c @@ -79,7 +79,7 @@ void action_operatortypes(void) WM_operatortype_append(ACT_OT_clean); WM_operatortype_append(ACT_OT_delete); WM_operatortype_append(ACT_OT_duplicate); - WM_operatortype_append(ACT_OT_insert); + WM_operatortype_append(ACT_OT_insert_keyframe); WM_operatortype_append(ACT_OT_copy); WM_operatortype_append(ACT_OT_paste); @@ -142,7 +142,7 @@ static void action_keymap_keyframes (wmWindowManager *wm, ListBase *keymap) WM_keymap_add_item(keymap, "ACT_OT_delete", DELKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "ACT_OT_duplicate", DKEY, KM_PRESS, KM_SHIFT, 0); - WM_keymap_add_item(keymap, "ACT_OT_insert", IKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "ACT_OT_insert_keyframe", IKEY, KM_PRESS, 0, 0); /* copy/paste */ WM_keymap_add_item(keymap, "ACT_OT_copy", CKEY, KM_PRESS, KM_CTRL, 0); diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index e38c24ed223..1fc4572b9c6 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -399,7 +399,103 @@ void GRAPH_OT_ghost_curves_clear (wmOperatorType *ot) /* ************************************************************************** */ /* GENERAL STUFF */ -// TODO: insertkey +/* ******************** Insert Keyframes Operator ************************* */ + +/* defines for insert keyframes tool */ +EnumPropertyItem prop_graphkeys_insertkey_types[] = { + {1, "ALL", 0, "All Channels", ""}, + {2, "SEL", 0, "Only Selected Channels", ""}, + {0, NULL, 0, NULL, NULL} +}; + +/* this function is responsible for snapping keyframes to frame-times */ +static void insert_graph_keys(bAnimContext *ac, short mode) +{ + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + Scene *scene= ac->scene; + float cfra= (float)CFRA; + short flag = 0; + + /* filter data */ + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY); + if (mode == 2) filter |= ANIMFILTER_SEL; + + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + /* init keyframing flag */ + if (IS_AUTOKEY_FLAG(AUTOMATKEY)) flag |= INSERTKEY_MATRIX; + if (IS_AUTOKEY_FLAG(INSERTNEEDED)) flag |= INSERTKEY_NEEDED; + // if (IS_AUTOKEY_MODE(EDITKEYS)) flag |= INSERTKEY_REPLACE; + + /* insert keyframes */ + for (ale= anim_data.first; ale; ale= ale->next) { + AnimData *adt= ANIM_nla_mapping_get(ac, ale); + FCurve *fcu= (FCurve *)ale->key_data; + + /* adjust current frame for NLA-mapping */ + if (adt) + cfra= BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); + else + cfra= (float)CFRA; + + /* if there's an id */ + if (ale->id) + insert_keyframe(ale->id, NULL, ((fcu->grp)?(fcu->grp->name):(NULL)), fcu->rna_path, fcu->array_index, cfra, flag); + else + insert_vert_fcurve(fcu, cfra, fcu->curval, 0); + } + + BLI_freelistN(&anim_data); +} + +/* ------------------- */ + +static int graphkeys_insertkey_exec(bContext *C, wmOperator *op) +{ + bAnimContext ac; + short mode; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + if (ac.datatype == ANIMCONT_GPENCIL) + return OPERATOR_CANCELLED; + + /* which channels to affect? */ + mode= RNA_enum_get(op->ptr, "type"); + + /* insert keyframes */ + insert_graph_keys(&ac, mode); + + /* validate keyframes after editing */ + ANIM_editkeyframes_refresh(&ac); + + /* set notifier that things have changed */ + ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES); + + return OPERATOR_FINISHED; +} + +void GRAPH_OT_insert_keyframe (wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Insert Keyframes"; + ot->idname= "GRAPH_OT_insert_keyframe"; + + /* api callbacks */ + ot->invoke= WM_menu_invoke; + ot->exec= graphkeys_insertkey_exec; + ot->poll= ED_operator_ipo_active; // xxx + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* id-props */ + RNA_def_enum(ot->srna, "type", prop_graphkeys_insertkey_types, 0, "Type", ""); +} /* ******************** Click-Insert Keyframes Operator ************************* */ diff --git a/source/blender/editors/space_graph/graph_header.c b/source/blender/editors/space_graph/graph_header.c index 0bd08625d68..b07bd4b0ded 100644 --- a/source/blender/editors/space_graph/graph_header.c +++ b/source/blender/editors/space_graph/graph_header.c @@ -201,7 +201,7 @@ static void graph_editmenu(bContext *C, uiLayout *layout, void *arg_unused) uiItemS(layout); - //uiItemO(layout, NULL, 0, "GRAPH_OT_insert"); + uiItemO(layout, NULL, 0, "GRAPH_OT_insert_keyframe"); uiItemO(layout, NULL, 0, "GRAPH_OT_fmodifier_add"); uiItemS(layout); diff --git a/source/blender/editors/space_graph/graph_intern.h b/source/blender/editors/space_graph/graph_intern.h index 93e3df1c728..d520a63c126 100644 --- a/source/blender/editors/space_graph/graph_intern.h +++ b/source/blender/editors/space_graph/graph_intern.h @@ -86,6 +86,7 @@ void GRAPH_OT_previewrange_set(struct wmOperatorType *ot); void GRAPH_OT_view_all(struct wmOperatorType *ot); void GRAPH_OT_click_insert(struct wmOperatorType *ot); +void GRAPH_OT_insert_keyframe(struct wmOperatorType *ot); void GRAPH_OT_copy(struct wmOperatorType *ot); void GRAPH_OT_paste(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c index f7799023f34..012bfd944b4 100644 --- a/source/blender/editors/space_graph/graph_ops.c +++ b/source/blender/editors/space_graph/graph_ops.c @@ -132,6 +132,7 @@ void graphedit_operatortypes(void) WM_operatortype_append(GRAPH_OT_copy); WM_operatortype_append(GRAPH_OT_paste); + WM_operatortype_append(GRAPH_OT_insert_keyframe); WM_operatortype_append(GRAPH_OT_click_insert); /* F-Curve Modifiers */ @@ -209,6 +210,7 @@ static void graphedit_keymap_keyframes (wmWindowManager *wm, ListBase *keymap) WM_keymap_add_item(keymap, "GRAPH_OT_duplicate", DKEY, KM_PRESS, KM_SHIFT, 0); /* insertkey */ + WM_keymap_add_item(keymap, "GRAPH_OT_insert_keyframe", IKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "GRAPH_OT_click_insert", LEFTMOUSE, KM_PRESS, KM_CTRL, 0); /* copy/paste */ From 66c86278204a3b9fac090c36539ce8efcb2bf0ba Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Wed, 1 Jul 2009 01:17:58 +0000 Subject: [PATCH 071/114] NLA SoC: Renamed a few options for the Mirror operators since their purpose wasn't clear (in practice) --- .../blender/editors/space_action/action_edit.c | 8 ++++---- .../blender/editors/space_action/action_header.c | 16 ++++++++-------- source/blender/editors/space_graph/graph_edit.c | 8 ++++---- .../blender/editors/space_graph/graph_header.c | 16 ++++++++-------- 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index 505ff18d7bd..910bcbef7e0 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -1198,10 +1198,10 @@ void ACT_OT_snap (wmOperatorType *ot) /* defines for mirror keyframes tool */ EnumPropertyItem prop_actkeys_mirror_types[] = { - {ACTKEYS_MIRROR_CFRA, "CFRA", 0, "Current frame", ""}, - {ACTKEYS_MIRROR_YAXIS, "YAXIS", 0, "Vertical Axis", ""}, - {ACTKEYS_MIRROR_XAXIS, "XAXIS", 0, "Horizontal Axis", ""}, - {ACTKEYS_MIRROR_MARKER, "MARKER", 0, "First Selected Marker", ""}, + {ACTKEYS_MIRROR_CFRA, "CFRA", 0, "By Times over Current frame", ""}, + {ACTKEYS_MIRROR_YAXIS, "YAXIS", 0, "By Times over Time=0", ""}, + {ACTKEYS_MIRROR_XAXIS, "XAXIS", 0, "By Values over Value=0", ""}, + {ACTKEYS_MIRROR_MARKER, "MARKER", 0, "By Times over First Selected Marker", ""}, {0, NULL, 0, NULL, NULL} }; diff --git a/source/blender/editors/space_action/action_header.c b/source/blender/editors/space_action/action_header.c index b2614411002..f4bb5b335a4 100644 --- a/source/blender/editors/space_action/action_header.c +++ b/source/blender/editors/space_action/action_header.c @@ -167,18 +167,18 @@ static void act_edit_transformmenu(bContext *C, uiLayout *layout, void *arg_unus static void act_edit_snapmenu(bContext *C, uiLayout *layout, void *arg_unused) { - uiItemEnumO(layout, "To Current Frame", 0, "ACT_OT_snap", "mode", ACTKEYS_SNAP_CFRA); - uiItemEnumO(layout, "To Nearest Frame", 0, "ACT_OT_snap", "mode", ACTKEYS_SNAP_NEAREST_FRAME); - uiItemEnumO(layout, "To Nearest Second", 0, "ACT_OT_snap", "mode", ACTKEYS_SNAP_NEAREST_SECOND); - uiItemEnumO(layout, "To Nearest Marker", 0, "ACT_OT_snap", "mode", ACTKEYS_SNAP_NEAREST_MARKER); + uiItemEnumO(layout, NULL, 0, "ACT_OT_snap", "type", ACTKEYS_SNAP_CFRA); + uiItemEnumO(layout, NULL, 0, "ACT_OT_snap", "type", ACTKEYS_SNAP_NEAREST_FRAME); + uiItemEnumO(layout, NULL, 0, "ACT_OT_snap", "type", ACTKEYS_SNAP_NEAREST_SECOND); + uiItemEnumO(layout, NULL, 0, "ACT_OT_snap", "type", ACTKEYS_SNAP_NEAREST_MARKER); } static void act_edit_mirrormenu(bContext *C, uiLayout *layout, void *arg_unused) { - uiItemEnumO(layout, "Over Current Frame", 0, "ACT_OT_mirror", "mode", ACTKEYS_MIRROR_CFRA); - uiItemEnumO(layout, "Over Vertical Axis", 0, "ACT_OT_mirror", "mode", ACTKEYS_MIRROR_YAXIS); - uiItemEnumO(layout, "Over Horizontal Axis", 0, "ACT_OT_mirror", "mode", ACTKEYS_MIRROR_XAXIS); - uiItemEnumO(layout, "Over Selected Marker", 0, "ACT_OT_mirror", "mode", ACTKEYS_MIRROR_MARKER); + uiItemEnumO(layout, NULL, 0, "ACT_OT_mirror", "type", ACTKEYS_MIRROR_CFRA); + uiItemEnumO(layout, NULL, 0, "ACT_OT_mirror", "type", ACTKEYS_MIRROR_YAXIS); + uiItemEnumO(layout, NULL, 0, "ACT_OT_mirror", "type", ACTKEYS_MIRROR_XAXIS); + uiItemEnumO(layout, NULL, 0, "ACT_OT_mirror", "type", ACTKEYS_MIRROR_MARKER); } static void act_edit_handlesmenu(bContext *C, uiLayout *layout, void *arg_unused) diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index 1fc4572b9c6..4ea14a365e4 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -1581,10 +1581,10 @@ void GRAPH_OT_snap (wmOperatorType *ot) /* defines for mirror keyframes tool */ EnumPropertyItem prop_graphkeys_mirror_types[] = { - {GRAPHKEYS_MIRROR_CFRA, "CFRA", 0, "Current frame", ""}, - {GRAPHKEYS_MIRROR_YAXIS, "YAXIS", 0, "Vertical Axis", ""}, - {GRAPHKEYS_MIRROR_XAXIS, "XAXIS", 0, "Horizontal Axis", ""}, - {GRAPHKEYS_MIRROR_MARKER, "MARKER", 0, "First Selected Marker", ""}, + {GRAPHKEYS_MIRROR_CFRA, "CFRA", 0, "By Times over Current frame", ""}, + {GRAPHKEYS_MIRROR_YAXIS, "YAXIS", 0, "By Times over Time=0", ""}, + {GRAPHKEYS_MIRROR_XAXIS, "XAXIS", 0, "By Values over Value=0", ""}, + {GRAPHKEYS_MIRROR_MARKER, "MARKER", 0, "By Times over First Selected Marker", ""}, {0, NULL, 0, NULL, NULL} }; diff --git a/source/blender/editors/space_graph/graph_header.c b/source/blender/editors/space_graph/graph_header.c index b07bd4b0ded..6c12b44f082 100644 --- a/source/blender/editors/space_graph/graph_header.c +++ b/source/blender/editors/space_graph/graph_header.c @@ -157,18 +157,18 @@ static void graph_edit_transformmenu(bContext *C, uiLayout *layout, void *arg_un static void graph_edit_snapmenu(bContext *C, uiLayout *layout, void *arg_unused) { - uiItemEnumO(layout, "To Current Frame", 0, "GRAPH_OT_snap", "mode", GRAPHKEYS_SNAP_CFRA); - uiItemEnumO(layout, "To Nearest Frame", 0, "GRAPH_OT_snap", "mode", GRAPHKEYS_SNAP_NEAREST_FRAME); - uiItemEnumO(layout, "To Nearest Second", 0, "GRAPH_OT_snap", "mode", GRAPHKEYS_SNAP_NEAREST_SECOND); - uiItemEnumO(layout, "To Nearest Marker", 0, "GRAPH_OT_snap", "mode", GRAPHKEYS_SNAP_NEAREST_MARKER); + uiItemEnumO(layout, NULL, 0, "GRAPH_OT_snap", "type", GRAPHKEYS_SNAP_CFRA); + uiItemEnumO(layout, NULL, 0, "GRAPH_OT_snap", "type", GRAPHKEYS_SNAP_NEAREST_FRAME); + uiItemEnumO(layout, NULL, 0, "GRAPH_OT_snap", "type", GRAPHKEYS_SNAP_NEAREST_SECOND); + uiItemEnumO(layout, NULL, 0, "GRAPH_OT_snap", "type", GRAPHKEYS_SNAP_NEAREST_MARKER); } static void graph_edit_mirrormenu(bContext *C, uiLayout *layout, void *arg_unused) { - uiItemEnumO(layout, "Over Current Frame", 0, "GRAPH_OT_mirror", "mode", GRAPHKEYS_MIRROR_CFRA); - uiItemEnumO(layout, "Over Vertical Axis", 0, "GRAPH_OT_mirror", "mode", GRAPHKEYS_MIRROR_YAXIS); - uiItemEnumO(layout, "Over Horizontal Axis", 0, "GRAPH_OT_mirror", "mode", GRAPHKEYS_MIRROR_XAXIS); - uiItemEnumO(layout, "Over Selected Marker", 0, "GRAPH_OT_mirror", "mode", GRAPHKEYS_MIRROR_MARKER); + uiItemEnumO(layout, NULL, 0, "GRAPH_OT_mirror", "type", GRAPHKEYS_MIRROR_CFRA); + uiItemEnumO(layout, NULL, 0, "GRAPH_OT_mirror", "type", GRAPHKEYS_MIRROR_YAXIS); + uiItemEnumO(layout, NULL, 0, "GRAPH_OT_mirror", "type", GRAPHKEYS_MIRROR_XAXIS); + uiItemEnumO(layout, NULL, 0, "GRAPH_OT_mirror", "type", GRAPHKEYS_MIRROR_MARKER); } static void graph_edit_handlesmenu(bContext *C, uiLayout *layout, void *arg_unused) From ede921fdfac1c76b8c54cae1723fbe9efd891939 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 2 Jul 2009 01:01:18 +0000 Subject: [PATCH 072/114] NLA SoC: Proper poll callbacks for Graph Editor For now, some of these polls may be a bit too restrictive, but at least we have some unified+cleaned bases to work from now (instead of relying on the generic ED_operator_area_active). --- .../editors/space_graph/graph_buttons.c | 28 -- .../blender/editors/space_graph/graph_draw.c | 40 --- .../blender/editors/space_graph/graph_edit.c | 46 +-- .../editors/space_graph/graph_intern.h | 9 + .../blender/editors/space_graph/graph_ops.c | 2 +- .../editors/space_graph/graph_select.c | 8 +- .../blender/editors/space_graph/graph_utils.c | 288 ++++++++++++++++++ 7 files changed, 325 insertions(+), 96 deletions(-) create mode 100644 source/blender/editors/space_graph/graph_utils.c diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c index ea4f017c9bb..f2dcd297866 100644 --- a/source/blender/editors/space_graph/graph_buttons.c +++ b/source/blender/editors/space_graph/graph_buttons.c @@ -1000,34 +1000,6 @@ static void graph_panel_modifiers(const bContext *C, Panel *pa) /* ******************* general ******************************** */ -/* Find 'active' F-Curve. It must be editable, since that's the purpose of these buttons (subject to change). - * We return the 'wrapper' since it contains valuable context info (about hierarchy), which will need to be freed - * when the caller is done with it. - */ -// TODO: move this to anim api with another name? -bAnimListElem *get_active_fcurve_channel (bAnimContext *ac) -{ - ListBase anim_data = {NULL, NULL}; - int filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_ACTIVE | ANIMFILTER_CURVESONLY); - int items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - - /* We take the first F-Curve only, since some other ones may have had 'active' flag set - * if they were from linked data. - */ - if (items) { - bAnimListElem *ale= (bAnimListElem *)anim_data.first; - - /* remove first item from list, then free the rest of the list and return the stored one */ - BLI_remlink(&anim_data, ale); - BLI_freelistN(&anim_data); - - return ale; - } - - /* no active F-Curve */ - return NULL; -} - void graph_buttons_register(ARegionType *art) { PanelType *pt; diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c index 6393b6877b9..66168f2ed87 100644 --- a/source/blender/editors/space_graph/graph_draw.c +++ b/source/blender/editors/space_graph/graph_draw.c @@ -775,46 +775,6 @@ void graph_draw_ghost_curves (bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, Vie glDisable(GL_BLEND); } -/* check if any FModifiers to draw controls for - fcm is 'active' modifier */ -static short fcurve_needs_draw_fmodifier_controls (FCurve *fcu, FModifier *fcm) -{ - /* don't draw if there aren't any modifiers at all */ - if (fcu->modifiers.first == NULL) - return 0; - - /* if there's an active modifier - don't draw if it doesn't drastically - * alter the curve... - */ - if (fcm) { - switch (fcm->type) { - /* clearly harmless */ - case FMODIFIER_TYPE_CYCLES: - return 0; - - /* borderline... */ - case FMODIFIER_TYPE_NOISE: - return 0; - } - } - - /* if only one modifier - don't draw if it is muted or disabled */ - if (fcu->modifiers.first == fcu->modifiers.last) { - fcm= fcu->modifiers.first; - if (fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) - return 0; - } - - /* if only active modifier - don't draw if it is muted or disabled */ - if (fcm) { - if (fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) - return 0; - } - - /* if we're still here, this means that there are modifiers with controls to be drawn */ - // FIXME: what happens if all the modifiers were muted/disabled - return 1; -} - /* This is called twice from space_graph.c -> graph_main_area_draw() * Unselected then selected F-Curves are drawn so that they do not occlude each other. */ diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index 4ea14a365e4..ca47e69cc75 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -189,7 +189,7 @@ void GRAPH_OT_previewrange_set (wmOperatorType *ot) /* api callbacks */ ot->exec= graphkeys_previewrange_exec; - ot->poll= ED_operator_areaactive; + ot->poll= graphop_visible_keyframes_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -236,7 +236,7 @@ void GRAPH_OT_view_all (wmOperatorType *ot) /* api callbacks */ ot->exec= graphkeys_viewall_exec; - ot->poll= ED_operator_areaactive; + ot->poll= graphop_visible_keyframes_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -347,7 +347,7 @@ void GRAPH_OT_ghost_curves_create (wmOperatorType *ot) /* api callbacks */ ot->exec= graphkeys_create_ghostcurves_exec; - ot->poll= ED_operator_areaactive; + ot->poll= graphop_visible_keyframes_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -390,7 +390,7 @@ void GRAPH_OT_ghost_curves_clear (wmOperatorType *ot) /* api callbacks */ ot->exec= graphkeys_clear_ghostcurves_exec; - ot->poll= ED_operator_areaactive; + ot->poll= ED_operator_ipo_active; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -488,7 +488,7 @@ void GRAPH_OT_insert_keyframe (wmOperatorType *ot) /* api callbacks */ ot->invoke= WM_menu_invoke; ot->exec= graphkeys_insertkey_exec; - ot->poll= ED_operator_ipo_active; // xxx + ot->poll= graphop_editable_keyframes_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -575,7 +575,7 @@ void GRAPH_OT_click_insert (wmOperatorType *ot) /* api callbacks */ ot->invoke= graphkeys_click_insert_invoke; ot->exec= graphkeys_click_insert_exec; - ot->poll= ED_operator_areaactive; // XXX active + editable poll + ot->poll= graphop_active_fcurve_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -657,7 +657,7 @@ void GRAPH_OT_copy (wmOperatorType *ot) /* api callbacks */ ot->exec= graphkeys_copy_exec; - ot->poll= ED_operator_areaactive; + ot->poll= graphop_editable_keyframes_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -696,7 +696,7 @@ void GRAPH_OT_paste (wmOperatorType *ot) /* api callbacks */ ot->exec= graphkeys_paste_exec; - ot->poll= ED_operator_areaactive; + ot->poll= graphop_editable_keyframes_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -764,7 +764,7 @@ void GRAPH_OT_duplicate (wmOperatorType *ot) /* api callbacks */ ot->invoke= graphkeys_duplicate_invoke; ot->exec= graphkeys_duplicate_exec; - ot->poll= ED_operator_areaactive; + ot->poll= graphop_editable_keyframes_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -825,7 +825,7 @@ void GRAPH_OT_delete (wmOperatorType *ot) /* api callbacks */ ot->invoke= WM_operator_confirm; ot->exec= graphkeys_delete_exec; - ot->poll= ED_operator_areaactive; + ot->poll= graphop_editable_keyframes_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -886,7 +886,7 @@ void GRAPH_OT_clean (wmOperatorType *ot) /* api callbacks */ //ot->invoke= // XXX we need that number popup for this! ot->exec= graphkeys_clean_exec; - ot->poll= ED_operator_areaactive; + ot->poll= graphop_editable_keyframes_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -967,7 +967,7 @@ void GRAPH_OT_bake (wmOperatorType *ot) /* api callbacks */ ot->invoke= WM_operator_confirm; // FIXME... ot->exec= graphkeys_bake_exec; - ot->poll= ED_operator_areaactive; + ot->poll= graphop_editable_keyframes_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -1092,7 +1092,7 @@ void GRAPH_OT_sample (wmOperatorType *ot) /* api callbacks */ ot->exec= graphkeys_sample_exec; - ot->poll= ED_operator_areaactive; + ot->poll= graphop_editable_keyframes_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -1167,7 +1167,7 @@ void GRAPH_OT_extrapolation_type (wmOperatorType *ot) /* api callbacks */ ot->invoke= WM_menu_invoke; ot->exec= graphkeys_expo_exec; - ot->poll= ED_operator_areaactive; + ot->poll= graphop_editable_keyframes_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -1235,7 +1235,7 @@ void GRAPH_OT_interpolation_type (wmOperatorType *ot) /* api callbacks */ ot->invoke= WM_menu_invoke; ot->exec= graphkeys_ipo_exec; - ot->poll= ED_operator_areaactive; + ot->poll= graphop_editable_keyframes_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -1322,7 +1322,7 @@ void GRAPH_OT_handletype (wmOperatorType *ot) /* api callbacks */ ot->invoke= WM_menu_invoke; ot->exec= graphkeys_handletype_exec; - ot->poll= ED_operator_areaactive; + ot->poll= graphop_editable_keyframes_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -1411,7 +1411,7 @@ void GRAPH_OT_euler_filter (wmOperatorType *ot) /* api callbacks */ ot->exec= graphkeys_euler_filter_exec; - ot->poll= ED_operator_areaactive; + ot->poll= graphop_editable_keyframes_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -1438,7 +1438,7 @@ static int graphkeys_framejump_exec(bContext *C, wmOperator *op) memset(&bed, 0, sizeof(BeztEditData)); /* loop over action data, averaging values */ - filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE| ANIMFILTER_CURVESONLY); + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_CURVESONLY); ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); for (ale= anim_data.first; ale; ale= ale->next) { @@ -1476,7 +1476,7 @@ void GRAPH_OT_frame_jump (wmOperatorType *ot) /* api callbacks */ ot->exec= graphkeys_framejump_exec; - ot->poll= ED_operator_areaactive; + ot->poll= graphop_visible_keyframes_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -1568,7 +1568,7 @@ void GRAPH_OT_snap (wmOperatorType *ot) /* api callbacks */ ot->invoke= WM_menu_invoke; ot->exec= graphkeys_snap_exec; - ot->poll= ED_operator_areaactive; + ot->poll= graphop_editable_keyframes_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -1679,7 +1679,7 @@ void GRAPH_OT_mirror (wmOperatorType *ot) /* api callbacks */ ot->invoke= WM_menu_invoke; ot->exec= graphkeys_mirror_exec; - ot->poll= ED_operator_areaactive; + ot->poll= graphop_editable_keyframes_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -1732,7 +1732,7 @@ void GRAPH_OT_smooth (wmOperatorType *ot) /* api callbacks */ ot->exec= graphkeys_smooth_exec; - ot->poll= ED_operator_areaactive; + ot->poll= graphop_editable_keyframes_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -1795,7 +1795,7 @@ void GRAPH_OT_fmodifier_add (wmOperatorType *ot) /* api callbacks */ ot->invoke= WM_menu_invoke; ot->exec= graph_fmodifier_add_exec; - ot->poll= ED_operator_areaactive; // XXX need active F-Curve + ot->poll= graphop_active_fcurve_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; diff --git a/source/blender/editors/space_graph/graph_intern.h b/source/blender/editors/space_graph/graph_intern.h index d520a63c126..fd7fe7cc6c9 100644 --- a/source/blender/editors/space_graph/graph_intern.h +++ b/source/blender/editors/space_graph/graph_intern.h @@ -141,8 +141,17 @@ void GRAPH_OT_ghost_curves_clear(struct wmOperatorType *ot); void GRAPH_OT_properties(struct wmOperatorType *ot); void graph_buttons_register(struct ARegionType *art); +/* ***************************************** */ +/* graph_utils.c */ + struct bAnimListElem *get_active_fcurve_channel(struct bAnimContext *ac); +short fcurve_needs_draw_fmodifier_controls(struct FCurve *fcu, struct FModifier *fcm); + +int graphop_visible_keyframes_poll(struct bContext *C); +int graphop_editable_keyframes_poll(struct bContext *C); +int graphop_active_fcurve_poll(struct bContext *C); + /* ***************************************** */ /* graph_ops.c */ void graphedit_keymap(struct wmWindowManager *wm); diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c index 012bfd944b4..d5e93dafaf0 100644 --- a/source/blender/editors/space_graph/graph_ops.c +++ b/source/blender/editors/space_graph/graph_ops.c @@ -92,7 +92,7 @@ void GRAPH_OT_view_togglehandles (wmOperatorType *ot) /* callbacks */ ot->exec= view_toggle_handles_exec; - ot->poll= ED_operator_areaactive; + ot->poll= ED_operator_ipo_active; } /* ************************** registration - operator types **********************************/ diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c index afe66ed179e..11af86ca83b 100644 --- a/source/blender/editors/space_graph/graph_select.c +++ b/source/blender/editors/space_graph/graph_select.c @@ -182,7 +182,7 @@ void GRAPH_OT_select_all_toggle (wmOperatorType *ot) /* api callbacks */ ot->exec= graphkeys_deselectall_exec; - ot->poll= ED_operator_areaactive; + ot->poll= graphop_visible_keyframes_poll; /* flags */ ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/; @@ -316,7 +316,7 @@ void GRAPH_OT_select_border(wmOperatorType *ot) ot->exec= graphkeys_borderselect_exec; ot->modal= WM_border_select_modal; - ot->poll= ED_operator_areaactive; + ot->poll= graphop_visible_keyframes_poll; /* flags */ ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/; @@ -506,7 +506,7 @@ void GRAPH_OT_select_column (wmOperatorType *ot) /* api callbacks */ ot->exec= graphkeys_columnselect_exec; - ot->poll= ED_operator_areaactive; + ot->poll= graphop_visible_keyframes_poll; /* flags */ ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/; @@ -926,7 +926,7 @@ void GRAPH_OT_clickselect (wmOperatorType *ot) /* api callbacks */ ot->invoke= graphkeys_clickselect_invoke; - ot->poll= ED_operator_areaactive; + ot->poll= graphop_visible_keyframes_poll; /* id-props */ // XXX should we make this into separate operators? diff --git a/source/blender/editors/space_graph/graph_utils.c b/source/blender/editors/space_graph/graph_utils.c new file mode 100644 index 00000000000..b1ec795a089 --- /dev/null +++ b/source/blender/editors/space_graph/graph_utils.c @@ -0,0 +1,288 @@ +/** + * $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, Joshua Leung + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include +#include +#include +#include + +#include "DNA_anim_types.h" +#include "DNA_action_types.h" +#include "DNA_object_types.h" +#include "DNA_space_types.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" +#include "DNA_userdef_types.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_arithb.h" +#include "BLI_blenlib.h" +#include "BLI_editVert.h" +#include "BLI_rand.h" + +#include "BKE_animsys.h" +#include "BKE_action.h" +#include "BKE_context.h" +#include "BKE_curve.h" +#include "BKE_customdata.h" +#include "BKE_depsgraph.h" +#include "BKE_fcurve.h" +#include "BKE_object.h" +#include "BKE_global.h" +#include "BKE_scene.h" +#include "BKE_screen.h" +#include "BKE_utildefines.h" + +#include "BIF_gl.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "ED_anim_api.h" +#include "ED_keyframing.h" +#include "ED_screen.h" +#include "ED_types.h" +#include "ED_util.h" + +#include "UI_interface.h" +#include "UI_resources.h" +#include "UI_view2d.h" + +#include "graph_intern.h" // own include + +/* ************************************************************** */ +/* Active F-Curve */ + +/* Find 'active' F-Curve. It must be editable, since that's the purpose of these buttons (subject to change). + * We return the 'wrapper' since it contains valuable context info (about hierarchy), which will need to be freed + * when the caller is done with it. + */ +bAnimListElem *get_active_fcurve_channel (bAnimContext *ac) +{ + ListBase anim_data = {NULL, NULL}; + int filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_ACTIVE | ANIMFILTER_CURVESONLY); + int items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + /* We take the first F-Curve only, since some other ones may have had 'active' flag set + * if they were from linked data. + */ + if (items) { + bAnimListElem *ale= (bAnimListElem *)anim_data.first; + + /* remove first item from list, then free the rest of the list and return the stored one */ + BLI_remlink(&anim_data, ale); + BLI_freelistN(&anim_data); + + return ale; + } + + /* no active F-Curve */ + return NULL; +} + +/* ************************************************************** */ +/* Operator Polling Callbacks */ + +/* check if any FModifiers to draw controls for - fcm is 'active' modifier + * used for the polling callbacks + also for drawing + */ +short fcurve_needs_draw_fmodifier_controls (FCurve *fcu, FModifier *fcm) +{ + /* don't draw if there aren't any modifiers at all */ + if (fcu->modifiers.first == NULL) + return 0; + + /* if there's an active modifier - don't draw if it doesn't drastically + * alter the curve... + */ + if (fcm) { + switch (fcm->type) { + /* clearly harmless */ + case FMODIFIER_TYPE_CYCLES: + return 0; + + /* borderline... */ + case FMODIFIER_TYPE_NOISE: + return 0; + } + } + + /* if only one modifier - don't draw if it is muted or disabled */ + if (fcu->modifiers.first == fcu->modifiers.last) { + fcm= fcu->modifiers.first; + if (fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) + return 0; + } + + /* if only active modifier - don't draw if it is muted or disabled */ + if (fcm) { + if (fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) + return 0; + } + + /* if we're still here, this means that there are modifiers with controls to be drawn */ + // FIXME: what happens if all the modifiers were muted/disabled + return 1; +} + +/* ------------------- */ + +/* Check if there are any visible keyframes (for selection tools) */ +int graphop_visible_keyframes_poll (bContext *C) +{ + bAnimContext ac; + bAnimListElem *ale; + 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; + + /* loop over the visible (selection doesn't matter) F-Curves, and see if they're suitable + * stopping on the first successful match + */ + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVESONLY); + items = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + if (items == 0) + return 0; + + for (ale = anim_data.first; ale; ale= ale->next) { + FCurve *fcu= (FCurve *)ale->data; + FModifier *fcm; + + /* visible curves for selection must fulfull the following criteria: + * - it has bezier keyframes + * - F-Curve modifiers do not interfere with the result too much + * (i.e. the modifier-control drawing check returns false) + */ + if (fcu->bezt == NULL) + continue; + fcm= fcurve_find_active_modifier(fcu); + + found= (fcurve_needs_draw_fmodifier_controls(fcu, fcm) == 0); + if (found) break; + } + + /* cleanup and return findings */ + BLI_freelistN(&anim_data); + return found; +} + +/* Check if there are any visible + editable keyframes (for editing tools) */ +int graphop_editable_keyframes_poll (bContext *C) +{ + bAnimContext ac; + bAnimListElem *ale; + 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; + + /* loop over the editable (selected + editable) F-Curves, and see if they're suitable + * stopping on the first successful match + */ + 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; + + for (ale = anim_data.first; ale; ale= ale->next) { + FCurve *fcu= (FCurve *)ale->data; + FModifier *fcm; + + /* editable curves must fulfull the following criteria: + * - it has bezier keyframes + * - it must not be protected from editing (this is already checked for with the foredit flag + * - F-Curve modifiers do not interfere with the result too much + * (i.e. the modifier-control drawing check returns false) + */ + if (fcu->bezt == NULL) + continue; + fcm= fcurve_find_active_modifier(fcu); + + found= (fcurve_needs_draw_fmodifier_controls(fcu, fcm) == 0); + if (found) break; + } + + /* cleanup and return findings */ + BLI_freelistN(&anim_data); + return found; +} + +/* has active F-Curve that's editable */ +int graphop_active_fcurve_poll (bContext *C) +{ + bAnimContext ac; + bAnimListElem *ale; + ScrArea *sa= CTX_wm_area(C); + short has_fcurve= 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; + + /* try to get the Active F-Curve */ + ale= get_active_fcurve_channel(&ac); + if (ale == NULL) + return 0; + + /* free temp data... */ + has_fcurve= ((ale->data) && (ale->type == ANIMTYPE_FCURVE)); + MEM_freeN(ale); + + /* return success */ + return has_fcurve; +} + +/* ************************************************************** */ From 1588de008a7c9c80d193034c0f8b4dc766620a38 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 2 Jul 2009 02:12:37 +0000 Subject: [PATCH 073/114] NLA SoC: Separated 'Built-In Function Generator' FModifier into a separate FModifier Started cleaning up FModifiers in preparation for allowing them to be used on NLA Strips. This commit separates the 'Built-in Function' mode for the Generator modifier out into its own modifier, since it was being quite frequently used (and the RNA wrapping for this used to be quite hackish). BACKWARDS COMPATABILITY WARNING: Old files with FModifiers saved (i.e. old 2.5 files, but not any others) will not load correctly as a result of these changes (the wrong modifiers will be shown). I've decided that there are not likely to be many files affected by this yet, but doing this will result in a much nicer modifiers-define list in the long run. --- source/blender/blenkernel/intern/fcurve.c | 256 +++++++++--------- .../editors/space_graph/graph_buttons.c | 129 +++------ .../editors/space_graph/graph_intern.h | 2 + source/blender/makesdna/DNA_anim_types.h | 45 ++- source/blender/makesrna/RNA_access.h | 2 +- source/blender/makesrna/intern/rna_fcurve.c | 109 ++------ 6 files changed, 231 insertions(+), 312 deletions(-) diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 27ca6332cdc..e52c63d1b21 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -1,5 +1,5 @@ /** - * $Id: fcurve.c 21023 2009-06-20 04:02:49Z aligorith $ + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -1314,11 +1314,6 @@ static FModifierTypeInfo FMI_MODNAME = { * 1) simple polynomial generator: * - Exanded form - (y = C[0]*(x^(n)) + C[1]*(x^(n-1)) + ... + C[n]) * - Factorised form - (y = (C[0][0]*x + C[0][1]) * (C[1][0]*x + C[1][1]) * ... * (C[n][0]*x + C[n][1])) - * 2) simple builin 'functions': - * of the form (y = C[0] * fn( C[1]*x + C[2] ) + C[3]) - * where fn() can be any one of: - * sin, cos, tan, ln, sqrt - * 3) expression... */ static void fcm_generator_free (FModifier *fcm) @@ -1408,45 +1403,11 @@ static void fcm_generator_verify (FModifier *fcm) data->coefficients= nc; data->arraysize= data->poly_order * 2; } - } - break; - - case FCM_GENERATOR_FUNCTION: /* builtin function */ - { - /* arraysize needs to be 4*/ - if (data->arraysize != 4) { - float *nc; - - /* free the old data */ - if (data->coefficients) - MEM_freeN(data->coefficients); - - /* make new coefficients array, and init using default values */ - nc= data->coefficients= MEM_callocN(sizeof(float)*4, "FMod_Generator_Coefs"); - data->arraysize= 4; - - nc[0]= 1.0f; - nc[1]= 1.0f; - nc[2]= 0.0f; - nc[3]= 0.0f; - } } break; } } -/* Unary 'normalised sine' function - * y = sin(PI + x) / (PI * x), - * except for x = 0 when y = 1. - */ -static double sinc (double x) -{ - if (fabs(x) < 0.0001) - return 1.0; - else - return sin(M_PI * x) / (M_PI * x); -} - static void fcm_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) { FMod_Generator *data= (FMod_Generator *)fcm->data; @@ -1509,86 +1470,6 @@ static void fcm_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, } } break; - - case FCM_GENERATOR_FUNCTION: /* builtin function */ - { - double arg= data->coefficients[1]*evaltime + data->coefficients[2]; - double (*fn)(double v) = NULL; - - /* get function pointer to the func to use: - * WARNING: must perform special argument validation hereto guard against crashes - */ - switch (data->func_type) - { - /* simple ones */ - case FCM_GENERATOR_FN_SIN: /* sine wave */ - fn= sin; - break; - case FCM_GENERATOR_FN_COS: /* cosine wave */ - fn= cos; - break; - case FCM_GENERATOR_FN_SINC: /* normalised sine wave */ - fn= sinc; - break; - - /* validation required */ - case FCM_GENERATOR_FN_TAN: /* tangent wave */ - { - /* check that argument is not on one of the discontinuities (i.e. 90deg, 270 deg, etc) */ - if IS_EQ(fmod((arg - M_PI_2), M_PI), 0.0) { - if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0) - *cvalue = 0.0f; /* no value possible here */ - } - else - fn= tan; - } - break; - case FCM_GENERATOR_FN_LN: /* natural log */ - { - /* check that value is greater than 1? */ - if (arg > 1.0f) { - fn= log; - } - else { - if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0) - *cvalue = 0.0f; /* no value possible here */ - } - } - break; - case FCM_GENERATOR_FN_SQRT: /* square root */ - { - /* no negative numbers */ - if (arg > 0.0f) { - fn= sqrt; - } - else { - if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0) - *cvalue = 0.0f; /* no value possible here */ - } - } - break; - - default: - printf("Invalid Function-Generator for F-Modifier - %d \n", data->func_type); - } - - /* execute function callback to set value if appropriate */ - if (fn) { - float value= (float)(data->coefficients[0]*fn(arg) + data->coefficients[3]); - - if (data->flag & FCM_GENERATOR_ADDITIVE) - *cvalue += value; - else - *cvalue= value; - } - } - break; - -#ifndef DISABLE_PYTHON - case FCM_GENERATOR_EXPRESSION: /* py-expression */ - // TODO... - break; -#endif /* DISABLE_PYTHON */ } } @@ -1607,6 +1488,128 @@ static FModifierTypeInfo FMI_GENERATOR = { fcm_generator_evaluate /* evaluate */ }; +/* Built-In Function Generator F-Curve Modifier --------------------------- */ + +/* This uses the general equation for equations: + * y = amplitude * fn(phase_multiplier*x + phase_offset) + y_offset + * + * where amplitude, phase_multiplier/offset, y_offset are user-defined coefficients, + * x is the evaluation 'time', and 'y' is the resultant value + * + * Functions available are + * sin, cos, tan, sinc (normalised sin), natural log, square root + */ + +static void fcm_fn_generator_new_data (void *mdata) +{ + FMod_FunctionGenerator *data= (FMod_FunctionGenerator *)mdata; + + /* set amplitude and phase multiplier to 1.0f so that something is generated */ + data->amplitude= 1.0f; + data->phase_multiplier= 1.0f; +} + +/* Unary 'normalised sine' function + * y = sin(PI + x) / (PI * x), + * except for x = 0 when y = 1. + */ +static double sinc (double x) +{ + if (fabs(x) < 0.0001) + return 1.0; + else + return sin(M_PI * x) / (M_PI * x); +} + +static void fcm_fn_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) +{ + FMod_FunctionGenerator *data= (FMod_FunctionGenerator *)fcm->data; + double arg= data->phase_multiplier*evaltime + data->phase_offset; + double (*fn)(double v) = NULL; + + /* get function pointer to the func to use: + * WARNING: must perform special argument validation hereto guard against crashes + */ + switch (data->type) + { + /* simple ones */ + case FCM_GENERATOR_FN_SIN: /* sine wave */ + fn= sin; + break; + case FCM_GENERATOR_FN_COS: /* cosine wave */ + fn= cos; + break; + case FCM_GENERATOR_FN_SINC: /* normalised sine wave */ + fn= sinc; + break; + + /* validation required */ + case FCM_GENERATOR_FN_TAN: /* tangent wave */ + { + /* check that argument is not on one of the discontinuities (i.e. 90deg, 270 deg, etc) */ + if IS_EQ(fmod((arg - M_PI_2), M_PI), 0.0) { + if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0) + *cvalue = 0.0f; /* no value possible here */ + } + else + fn= tan; + } + break; + case FCM_GENERATOR_FN_LN: /* natural log */ + { + /* check that value is greater than 1? */ + if (arg > 1.0f) { + fn= log; + } + else { + if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0) + *cvalue = 0.0f; /* no value possible here */ + } + } + break; + case FCM_GENERATOR_FN_SQRT: /* square root */ + { + /* no negative numbers */ + if (arg > 0.0f) { + fn= sqrt; + } + else { + if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0) + *cvalue = 0.0f; /* no value possible here */ + } + } + break; + + default: + printf("Invalid Function-Generator for F-Modifier - %d \n", data->type); + } + + /* execute function callback to set value if appropriate */ + if (fn) { + float value= (float)(data->amplitude*fn(arg) + data->value_offset); + + if (data->flag & FCM_GENERATOR_ADDITIVE) + *cvalue += value; + else + *cvalue= value; + } +} + +static FModifierTypeInfo FMI_FN_GENERATOR = { + FMODIFIER_TYPE_FN_GENERATOR, /* type */ + sizeof(FMod_FunctionGenerator), /* size */ + FMI_TYPE_GENERATE_CURVE, /* action type */ + FMI_REQUIRES_NOTHING, /* requirements */ + "Built-In Function", /* name */ + "FMod_FunctionGenerator", /* struct name */ + NULL, /* free data */ + NULL, /* copy data */ + fcm_fn_generator_new_data, /* new data */ + NULL, /* verify */ + NULL, /* evaluate time */ + fcm_fn_generator_evaluate /* evaluate */ +}; + /* Envelope F-Curve Modifier --------------------------- */ static void fcm_envelope_free (FModifier *fcm) @@ -2081,12 +2084,13 @@ static void fmods_init_typeinfo () { fmodifiersTypeInfo[0]= NULL; /* 'Null' F-Curve Modifier */ fmodifiersTypeInfo[1]= &FMI_GENERATOR; /* Generator F-Curve Modifier */ - fmodifiersTypeInfo[2]= &FMI_ENVELOPE; /* Envelope F-Curve Modifier */ - fmodifiersTypeInfo[3]= &FMI_CYCLES; /* Cycles F-Curve Modifier */ - fmodifiersTypeInfo[4]= &FMI_NOISE; /* Apply-Noise F-Curve Modifier */ - fmodifiersTypeInfo[5]= NULL/*&FMI_FILTER*/; /* Filter F-Curve Modifier */ // XXX unimplemented - fmodifiersTypeInfo[6]= &FMI_PYTHON; /* Custom Python F-Curve Modifier */ - fmodifiersTypeInfo[7]= &FMI_LIMITS; /* Limits F-Curve Modifier */ + fmodifiersTypeInfo[2]= &FMI_FN_GENERATOR; /* Built-In Function Generator F-Curve Modifier */ + fmodifiersTypeInfo[3]= &FMI_ENVELOPE; /* Envelope F-Curve Modifier */ + fmodifiersTypeInfo[4]= &FMI_CYCLES; /* Cycles F-Curve Modifier */ + fmodifiersTypeInfo[5]= &FMI_NOISE; /* Apply-Noise F-Curve Modifier */ + fmodifiersTypeInfo[6]= NULL/*&FMI_FILTER*/; /* Filter F-Curve Modifier */ // XXX unimplemented + fmodifiersTypeInfo[7]= &FMI_PYTHON; /* Custom Python F-Curve Modifier */ + fmodifiersTypeInfo[8]= &FMI_LIMITS; /* Limits F-Curve Modifier */ } /* This function should be used for getting the appropriate type-info when only diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c index f2dcd297866..e68ee53521d 100644 --- a/source/blender/editors/space_graph/graph_buttons.c +++ b/source/blender/editors/space_graph/graph_buttons.c @@ -404,8 +404,7 @@ static void delete_fmodifier_cb (bContext *C, void *fcu_v, void *fcm_v) static void draw_modifier__generator(uiBlock *block, FCurve *fcu, FModifier *fcm, int *yco, short *height, short width, short active, int rb_col) { FMod_Generator *data= (FMod_Generator *)fcm->data; - char gen_mode[]="Generator Type%t|Expanded Polynomial%x0|Factorised Polynomial%x1|Built-In Function%x2|Expression%x3"; - char fn_type[]="Built-In Function%t|Sin%x0|Cos%x1|Tan%x2|Square Root%x3|Natural Log%x4|Normalised Sin%x5"; + char gen_mode[]="Generator Type%t|Expanded Polynomial%x0|Factorised Polynomial%x1"; int cy= *yco - 30; uiBut *but; @@ -418,22 +417,16 @@ static void draw_modifier__generator(uiBlock *block, FCurve *fcu, FModifier *fcm case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* factorised polynomial */ (*height) += 20 * data->poly_order + 15; break; - case FCM_GENERATOR_FUNCTION: /* builtin function */ - (*height) += 55; // xxx - break; - case FCM_GENERATOR_EXPRESSION: /* py-expression */ - // xxx nothing to draw - break; } /* basic settings (backdrop + mode selector + some padding) */ DRAW_BACKDROP((*height)); uiBlockBeginAlign(block); - but= uiDefButS(block, MENU, B_FMODIFIER_REDRAW, gen_mode, 10,cy,width-30,19, &data->mode, 0, 0, 0, 0, "Selects type of generator algorithm."); + but= uiDefButI(block, MENU, B_FMODIFIER_REDRAW, gen_mode, 10,cy,width-30,19, &data->mode, 0, 0, 0, 0, "Selects type of generator algorithm."); uiButSetFunc(but, validate_fmodifier_cb, fcu, fcm); cy -= 20; - uiDefButBitS(block, TOG, FCM_GENERATOR_ADDITIVE, B_FMODIFIER_REDRAW, "Additive", 10,cy,width-30,19, &data->flag, 0, 0, 0, 0, "Values generated by this modifier are applied on top of the existing values instead of overwriting them"); + uiDefButBitI(block, TOG, FCM_GENERATOR_ADDITIVE, B_FMODIFIER_REDRAW, "Additive", 10,cy,width-30,19, &data->flag, 0, 0, 0, 0, "Values generated by this modifier are applied on top of the existing values instead of overwriting them"); cy -= 35; uiBlockEndAlign(block); @@ -446,7 +439,7 @@ static void draw_modifier__generator(uiBlock *block, FCurve *fcu, FModifier *fcm unsigned int i; /* draw polynomial order selector */ - but= uiDefButS(block, NUM, B_FMODIFIER_REDRAW, "Poly Order: ", 10,cy,width-30,19, &data->poly_order, 1, 100, 0, 0, "'Order' of the Polynomial - for a polynomial with n terms, 'order' is n-1"); + but= uiDefButI(block, NUM, B_FMODIFIER_REDRAW, "Poly Order: ", 10,cy,width-30,19, &data->poly_order, 1, 100, 0, 0, "'Order' of the Polynomial - for a polynomial with n terms, 'order' is n-1"); uiButSetFunc(but, validate_fmodifier_cb, fcu, fcm); cy -= 35; @@ -481,7 +474,7 @@ static void draw_modifier__generator(uiBlock *block, FCurve *fcu, FModifier *fcm unsigned int i; /* draw polynomial order selector */ - but= uiDefButS(block, NUM, B_FMODIFIER_REDRAW, "Poly Order: ", 10,cy,width-30,19, &data->poly_order, 1, 100, 0, 0, "'Order' of the Polynomial - for a polynomial with n terms, 'order' is n-1"); + but= uiDefButI(block, NUM, B_FMODIFIER_REDRAW, "Poly Order: ", 10,cy,width-30,19, &data->poly_order, 1, 100, 0, 0, "'Order' of the Polynomial - for a polynomial with n terms, 'order' is n-1"); uiButSetFunc(but, validate_fmodifier_cb, fcu, fcm); cy -= 35; @@ -510,82 +503,42 @@ static void draw_modifier__generator(uiBlock *block, FCurve *fcu, FModifier *fcm } } break; - - case FCM_GENERATOR_FUNCTION: /* built-in function */ - { - float *cp= data->coefficients; - - /* draw function selector */ - but= uiDefButS(block, MENU, B_FMODIFIER_REDRAW, fn_type, 10,cy,width-30,19, &data->func_type, 0, 0, 0, 0, "Built-In Function to use"); - uiButSetFunc(but, validate_fmodifier_cb, fcu, fcm); - cy -= 35; - - /* draw controls for equation of coefficients */ - /* row 1 */ - { - uiDefBut(block, LABEL, 1, "y = ", 0, cy, 50, 20, NULL, 0.0, 0.0, 0, 0, ""); - - uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 50, cy, 150, 20, cp+3, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "Coefficient (D) for function"); - uiDefBut(block, LABEL, 1, "+", 200, cy, 30, 20, NULL, 0.0, 0.0, 0, 0, ""); - cy -= 20; - } - - /* row 2 */ - { - char func_name[32]; - - /* coefficient outside bracket */ - uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 5, cy, 80, 20, cp, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "Coefficient (A) for function"); - - /* opening bracket */ - switch (data->func_type) - { - case FCM_GENERATOR_FN_SIN: /* sine wave */ - sprintf(func_name, "sin("); - break; - case FCM_GENERATOR_FN_COS: /* cosine wave */ - sprintf(func_name, "cos("); - break; - case FCM_GENERATOR_FN_TAN: /* tangent wave */ - sprintf(func_name, "tan("); - break; - case FCM_GENERATOR_FN_LN: /* natural log */ - sprintf(func_name, "ln("); - break; - case FCM_GENERATOR_FN_SQRT: /* square root */ - sprintf(func_name, "sqrt("); - break; - case FCM_GENERATOR_FN_SINC: /* normalised sine wave */ - sprintf(func_name, "sinc("); - break; - default: /* unknown */ - sprintf(func_name, "("); - break; - } - uiDefBut(block, LABEL, 1, func_name, 85, cy, 40, 20, NULL, 0.0, 0.0, 0, 0, ""); - - /* coefficients inside bracket */ - uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 120, cy, 75, 20, cp+1, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "Coefficient (B) of x"); - - uiDefBut(block, LABEL, 1, "x+", 195, cy, 30, 20, NULL, 0.0, 0.0, 0, 0, ""); - - uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 225, cy, 80, 20, cp+2, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "Coefficient (C) of function"); - - /* closing bracket */ - uiDefBut(block, LABEL, 1, ")", 300, cy, 30, 20, NULL, 0.0, 0.0, 0, 0, ""); - cy -= 20; - } - } - break; - - case FCM_GENERATOR_EXPRESSION: /* py-expression */ - // TODO... - break; } } /* --------------- */ +/* draw settings for noise modifier */ +static void draw_modifier__fn_generator(uiBlock *block, FCurve *fcu, FModifier *fcm, int *yco, short *height, short width, short active, int rb_col) +{ + FMod_FunctionGenerator *data= (FMod_FunctionGenerator *)fcm->data; + int cy= (*yco - 30), cy1= (*yco - 50), cy2= (*yco - 70); + char fn_type[]="Built-In Function%t|Sin%x0|Cos%x1|Tan%x2|Square Root%x3|Natural Log%x4|Normalised Sin%x5"; + + /* set the height */ + (*height) = 80; + + /* basic settings (backdrop + some padding) */ + DRAW_BACKDROP((*height)); + + uiDefButI(block, MENU, B_FMODIFIER_REDRAW, fn_type, + 3, cy, 300, 20, &data->type, 0, 0, 0, 0, "Type of function used to generate values"); + + + uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Amplitude:", + 3, cy1, 150, 20, &data->amplitude, 0.000001, 10000.0, 0.01, 3, "Scale factor determining the maximum/minimum values."); + uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Value Offset:", + 3, cy2, 150, 20, &data->value_offset, 0.0, 10000.0, 0.01, 3, "Constant factor to offset values by."); + + uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Phase Multiplier:", + 155, cy1, 150, 20, &data->phase_multiplier, 0.0, 100000.0, 0.1, 3, "Scale factor determining the 'speed' of the function."); + uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Phase Offset:", + 155, cy2, 150, 20, &data->phase_offset, 0.0, 100000.0, 0.1, 3, "Constant factor to offset time by for function."); + +} + +/* --------------- */ + /* draw settings for cycles modifier */ static void draw_modifier__cycles(uiBlock *block, FCurve *fcu, FModifier *fcm, int *yco, short *height, short width, short active, int rb_col) { @@ -621,7 +574,7 @@ static void draw_modifier__noise(uiBlock *block, FCurve *fcu, FModifier *fcm, in { FMod_Noise *data= (FMod_Noise *)fcm->data; int cy= (*yco - 30), cy1= (*yco - 50), cy2= (*yco - 70); - char cyc_mode[]="Modification %t|Replace %x0|Add %x1|Subtract %x2|Multiply %x3"; + char blend_mode[]="Modification %t|Replace %x0|Add %x1|Subtract %x2|Multiply %x3"; /* set the height */ (*height) = 80; @@ -629,8 +582,8 @@ static void draw_modifier__noise(uiBlock *block, FCurve *fcu, FModifier *fcm, in /* basic settings (backdrop + some padding) */ DRAW_BACKDROP((*height)); - uiDefButS(block, MENU, B_FMODIFIER_REDRAW, cyc_mode, - 3, cy, 150, 20, &data->modification, 0, 0, 0, 0, "Method of modifying the existing F-Curve use before first keyframe"); + uiDefButS(block, MENU, B_FMODIFIER_REDRAW, blend_mode, + 3, cy, 150, 20, &data->modification, 0, 0, 0, 0, "Method of combining the results of this modifier and other modifiers."); uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Size:", 3, cy1, 150, 20, &data->size, 0.000001, 10000.0, 0.01, 3, ""); @@ -946,6 +899,10 @@ static void graph_panel_modifier_draw(uiBlock *block, FCurve *fcu, FModifier *fc draw_modifier__generator(block, fcu, fcm, yco, &height, width, active, rb_col); break; + case FMODIFIER_TYPE_FN_GENERATOR: /* Built-In Function Generator */ + draw_modifier__fn_generator(block, fcu, fcm, yco, &height, width, active, rb_col); + break; + case FMODIFIER_TYPE_CYCLES: /* Cycles */ draw_modifier__cycles(block, fcu, fcm, yco, &height, width, active, rb_col); break; diff --git a/source/blender/editors/space_graph/graph_intern.h b/source/blender/editors/space_graph/graph_intern.h index fd7fe7cc6c9..86e5451122d 100644 --- a/source/blender/editors/space_graph/graph_intern.h +++ b/source/blender/editors/space_graph/graph_intern.h @@ -32,6 +32,8 @@ struct bContext; struct wmWindowManager; struct bAnimContext; struct bAnimListElem; +struct FCurve; +struct FModifier; struct SpaceIpo; struct ScrArea; struct ARegion; diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h index 2b089530236..ad3edde6552 100644 --- a/source/blender/makesdna/DNA_anim_types.h +++ b/source/blender/makesdna/DNA_anim_types.h @@ -1,5 +1,5 @@ /** - * $Id: DNA_anim_types.h 21023 2009-06-20 04:02:49Z aligorith $ + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -66,6 +66,7 @@ typedef struct FModifier { enum { FMODIFIER_TYPE_NULL = 0, FMODIFIER_TYPE_GENERATOR, + FMODIFIER_TYPE_FN_GENERATOR, FMODIFIER_TYPE_ENVELOPE, FMODIFIER_TYPE_CYCLES, FMODIFIER_TYPE_NOISE, /* unimplemented - generate variations using some basic noise generator... */ @@ -91,39 +92,55 @@ enum { /* --- */ -/* generator modifier data */ +/* Generator modifier data */ typedef struct FMod_Generator { - /* generator based on PyExpression */ - char expression[256]; /* python expression to use as generator */ - /* general generator information */ float *coefficients; /* coefficients array */ unsigned int arraysize; /* size of the coefficients array */ - short poly_order; /* order of polynomial generated (i.e. 1 for linear, 2 for quadratic) */ - short func_type; /* builtin math function eFMod_Generator_Functions */ - - int pad; + int poly_order; /* order of polynomial generated (i.e. 1 for linear, 2 for quadratic) */ + int mode; /* which 'generator' to use eFMod_Generator_Modes */ /* settings */ - short flag; /* settings */ - short mode; /* which 'generator' to use eFMod_Generator_Modes */ + int flag; /* settings */ } FMod_Generator; /* generator modes */ enum { FCM_GENERATOR_POLYNOMIAL = 0, FCM_GENERATOR_POLYNOMIAL_FACTORISED, - FCM_GENERATOR_FUNCTION, - FCM_GENERATOR_EXPRESSION, } eFMod_Generator_Modes; -/* generator flags */ + +/* generator flags + * - shared by Generator and Function Generator + */ enum { /* generator works in conjunction with other modifiers (i.e. doesn't replace those before it) */ FCM_GENERATOR_ADDITIVE = (1<<0), } eFMod_Generator_Flags; + +/* 'Built-In Function' Generator modifier data + * + * This uses the general equation for equations: + * y = amplitude * fn(phase_multiplier*x + phase_offset) + y_offset + * + * where amplitude, phase_multiplier/offset, y_offset are user-defined coefficients, + * x is the evaluation 'time', and 'y' is the resultant value + */ +typedef struct FMod_FunctionGenerator { + /* coefficients for general equation (as above) */ + float amplitude; + float phase_multiplier; + float phase_offset; + float value_offset; + + /* flags */ + int type; /* eFMod_Generator_Functions */ + int flag; /* eFMod_Generator_flags */ +} FMod_FunctionGenerator; + /* 'function' generator types */ enum { FCM_GENERATOR_FN_SIN = 0, diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index dda0d57f8ad..cf74a863401 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -177,8 +177,8 @@ extern StructRNA RNA_FCurve; extern StructRNA RNA_FModifier; extern StructRNA RNA_FModifierCycles; extern StructRNA RNA_FModifierEnvelope; +extern StructRNA RNA_FModifierFunctionGenerator; extern StructRNA RNA_FModifierGenerator; -extern StructRNA RNA_FModifierGenerator_Function; extern StructRNA RNA_FModifierGenerator_PolyExpanded; extern StructRNA RNA_FModifierLimits; extern StructRNA RNA_FModifierNoise; diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c index a1cd95c9d90..4a83b80a6cf 100644 --- a/source/blender/makesrna/intern/rna_fcurve.c +++ b/source/blender/makesrna/intern/rna_fcurve.c @@ -37,6 +37,7 @@ EnumPropertyItem fmodifier_type_items[] = { {FMODIFIER_TYPE_NULL, "NULL", 0, "Invalid", ""}, {FMODIFIER_TYPE_GENERATOR, "GENERATOR", 0, "Generator", ""}, + {FMODIFIER_TYPE_FN_GENERATOR, "FNGENERATOR", 0, "Built-In Function", ""}, {FMODIFIER_TYPE_ENVELOPE, "ENVELOPE", 0, "Envelope", ""}, {FMODIFIER_TYPE_CYCLES, "CYCLES", 0, "Cycles", ""}, {FMODIFIER_TYPE_NOISE, "NOISE", 0, "Noise", ""}, @@ -47,62 +48,6 @@ EnumPropertyItem fmodifier_type_items[] = { #ifdef RNA_RUNTIME -float FModGenFunc_amplitude_get(PointerRNA *ptr) -{ - FModifier *fcm = (FModifier *)(ptr->data); - FMod_Generator *data= (FMod_Generator*)(fcm->data); - return (data->coefficients) ? (float)data->coefficients[0] : 1.0f; -} - -void FModGenFunc_amplitude_set(PointerRNA *ptr, float value) -{ - FModifier *fcm = (FModifier *)(ptr->data); - FMod_Generator *data= (FMod_Generator*)(fcm->data); - if (data->coefficients) data->coefficients[0]= value; -} - -float FModGenFunc_pre_multiplier_get(PointerRNA *ptr) -{ - FModifier *fcm = (FModifier *)(ptr->data); - FMod_Generator *data= (FMod_Generator*)(fcm->data); - return (data->coefficients) ? (float)data->coefficients[1] : 1.0f; -} - -void FModGenFunc_pre_multiplier_set(PointerRNA *ptr, float value) -{ - FModifier *fcm = (FModifier *)(ptr->data); - FMod_Generator *data= (FMod_Generator*)(fcm->data); - if (data->coefficients) data->coefficients[1]= value; -} - -float FModGenFunc_x_offset_get(PointerRNA *ptr) -{ - FModifier *fcm = (FModifier *)(ptr->data); - FMod_Generator *data= (FMod_Generator*)(fcm->data); - return (data->coefficients) ? (float)data->coefficients[2] : 0.0f; -} - -void FModGenFunc_x_offset_set(PointerRNA *ptr, float value) -{ - FModifier *fcm = (FModifier *)(ptr->data); - FMod_Generator *data= (FMod_Generator*)(fcm->data); - if (data->coefficients) data->coefficients[2]= value; -} - -float FModGenFunc_y_offset_get(PointerRNA *ptr) -{ - FModifier *fcm = (FModifier *)(ptr->data); - FMod_Generator *data= (FMod_Generator*)(fcm->data); - return (data->coefficients) ? (float)data->coefficients[3] : 0.0f; -} - -void FModGenFunc_y_offset_set(PointerRNA *ptr, float value) -{ - FModifier *fcm = (FModifier *)(ptr->data); - FMod_Generator *data= (FMod_Generator*)(fcm->data); - if (data->coefficients) data->coefficients[3]= value; -} - /* --------- */ StructRNA *rna_FModifierType_refine(struct PointerRNA *ptr) @@ -118,13 +63,12 @@ StructRNA *rna_FModifierType_refine(struct PointerRNA *ptr) case FCM_GENERATOR_POLYNOMIAL: return &RNA_FModifierGenerator_PolyExpanded; //case FCM_GENERATOR_POLYNOMIAL_FACTORISED: - case FCM_GENERATOR_FUNCTION: - return &RNA_FModifierGenerator_Function; - //case FCM_GENERATOR_EXPRESSION: default: return &RNA_FModifierGenerator; } } + case FMODIFIER_TYPE_FN_GENERATOR: + return &RNA_FModifierFunctionGenerator; case FMODIFIER_TYPE_ENVELOPE: return &RNA_FModifierEnvelope; case FMODIFIER_TYPE_CYCLES: @@ -222,8 +166,6 @@ static void rna_def_fmodifier_generator_common(StructRNA *srna) static EnumPropertyItem prop_mode_items[] = { {FCM_GENERATOR_POLYNOMIAL, "POLYNOMIAL", 0, "Expanded Polynomial", ""}, {FCM_GENERATOR_POLYNOMIAL_FACTORISED, "POLYNOMIAL_FACTORISED", 0, "Factorised Polynomial", ""}, - {FCM_GENERATOR_FUNCTION, "FUNCTION", 0, "Built-In Function", ""}, - {FCM_GENERATOR_EXPRESSION, "EXPRESSION", 0, "Expression", ""}, {0, NULL, 0, NULL, NULL}}; /* struct wrapping settings */ @@ -273,7 +215,7 @@ static void rna_def_fmodifier_generator_polyexpanded(BlenderRNA *brna) //RNA_def_property_ui_text(prop, "Coefficients", "Coefficients for 'x' (starting from lowest power)."); } -static void rna_def_fmodifier_generator_function(BlenderRNA *brna) +static void rna_def_fmodifier_function_generator(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; @@ -286,35 +228,32 @@ static void rna_def_fmodifier_generator_function(BlenderRNA *brna) {4, "LN", 0, "Natural Logarithm", ""}, {5, "SINC", 0, "Normalised Sine", "sin(x) / x"}, {0, NULL, 0, NULL, NULL}}; - - srna= RNA_def_struct(brna, "FModifierGenerator_Function", "FModifier"); - RNA_def_struct_ui_text(srna, "Built-In Function Generator", "Generates values for modified F-Curve using Built-In Function."); - - /* common settings */ - rna_def_fmodifier_generator_common(srna); - - /* type */ - prop= RNA_def_property(srna, "func_type", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, prop_type_items); - RNA_def_property_ui_text(prop, "Type", "Type of Built-In function to use as generator."); + srna= RNA_def_struct(brna, "FModifierFunctionGenerator", "FModifier"); + RNA_def_struct_ui_text(srna, "Built-In Function F-Curve Modifier", "Generates values using a Built-In Function."); + RNA_def_struct_sdna_from(srna, "FMod_FunctionGenerator", "data"); /* coefficients */ prop= RNA_def_property(srna, "amplitude", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_funcs(prop, "FModGenFunc_amplitude_get", "FModGenFunc_amplitude_set", NULL); - RNA_def_property_ui_text(prop, "Amplitude", "Scale factor for y-values generated by the function."); + RNA_def_property_ui_text(prop, "Amplitude", "Scale factor determining the maximum/minimum values."); - prop= RNA_def_property(srna, "pre_multiplier", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_funcs(prop, "FModGenFunc_pre_multiplier_get", "FModGenFunc_pre_multiplier_set", NULL); - RNA_def_property_ui_text(prop, "PreMultiplier", "Scale factor for x-value inputs to function."); + prop= RNA_def_property(srna, "phase_multiplier", PROP_FLOAT, PROP_NONE); + RNA_def_property_ui_text(prop, "Phase Multiplier", "Scale factor determining the 'speed' of the function."); - prop= RNA_def_property(srna, "x_offset", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_funcs(prop, "FModGenFunc_x_offset_get", "FModGenFunc_x_offset_set", NULL); - RNA_def_property_ui_text(prop, "X Offset", "Offset for x-value inputs to function."); + prop= RNA_def_property(srna, "phase_offset", PROP_FLOAT, PROP_NONE); + RNA_def_property_ui_text(prop, "Phase Offset", "Constant factor to offset time by for function."); - prop= RNA_def_property(srna, "y_offset", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_funcs(prop, "FModGenFunc_y_offset_get", "FModGenFunc_y_offset_set", NULL); - RNA_def_property_ui_text(prop, "Y Offset", "Offset for y-values generated by the function."); + prop= RNA_def_property(srna, "value_offset", PROP_FLOAT, PROP_NONE); + RNA_def_property_ui_text(prop, "Value Offset", "Constant factor to offset values by."); + + /* flags */ + prop= RNA_def_property(srna, "additive", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", FCM_GENERATOR_ADDITIVE); + RNA_def_property_ui_text(prop, "Additive", "Values generated by this modifier are applied on top of the existing values instead of overwriting them."); + + prop= RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, prop_type_items); + RNA_def_property_ui_text(prop, "Type", "Type of built-in function to use."); } /* --------- */ @@ -646,7 +585,7 @@ void RNA_def_fcurve(BlenderRNA *brna) rna_def_fmodifier_generator(brna); rna_def_fmodifier_generator_polyexpanded(brna); - rna_def_fmodifier_generator_function(brna); + rna_def_fmodifier_function_generator(brna); rna_def_fmodifier_envelope(brna); rna_def_fmodifier_cycles(brna); rna_def_fmodifier_python(brna); From 78939898c735d6f2048e9fc2aa64a3188ff5732f Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 2 Jul 2009 02:53:18 +0000 Subject: [PATCH 074/114] NLA SoC: Adding some files that seem to have been missed during some merges. Hopefully all of these should really be in the repositry... --- release/scripts/animation_clean.py | 192 ++ release/scripts/image_2d_cutout.py | 559 ++++ release/scripts/object_active_to_other.py | 58 + .../scripttemplate_gamelogic_module.py | 45 + release/scripts/textplugin_convert_ge.py | 863 +++++ release/scripts/wizard_bolt_factory.py | 2804 +++++++++++++++++ release/scripts/wizard_landscape_ant.py | 2148 +++++++++++++ release/ui/space_sequencer.py | 559 ++++ .../Converter/BL_ModifierDeformer.cpp | 183 ++ .../Converter/BL_ModifierDeformer.h | 107 + source/gameengine/Ketsji/KX_PythonSeq.cpp | 382 +++ source/gameengine/Ketsji/KX_PythonSeq.h | 60 + source/gameengine/PyDoc/API_intro.py | 103 + source/gameengine/SceneGraph/SG_DList.h | 161 + source/gameengine/SceneGraph/SG_QList.h | 157 + 15 files changed, 8381 insertions(+) create mode 100644 release/scripts/animation_clean.py create mode 100644 release/scripts/image_2d_cutout.py create mode 100644 release/scripts/object_active_to_other.py create mode 100644 release/scripts/scripttemplate_gamelogic_module.py create mode 100644 release/scripts/textplugin_convert_ge.py create mode 100644 release/scripts/wizard_bolt_factory.py create mode 100644 release/scripts/wizard_landscape_ant.py create mode 100644 release/ui/space_sequencer.py create mode 100644 source/gameengine/Converter/BL_ModifierDeformer.cpp create mode 100644 source/gameengine/Converter/BL_ModifierDeformer.h create mode 100644 source/gameengine/Ketsji/KX_PythonSeq.cpp create mode 100644 source/gameengine/Ketsji/KX_PythonSeq.h create mode 100644 source/gameengine/PyDoc/API_intro.py create mode 100644 source/gameengine/SceneGraph/SG_DList.h create mode 100644 source/gameengine/SceneGraph/SG_QList.h diff --git a/release/scripts/animation_clean.py b/release/scripts/animation_clean.py new file mode 100644 index 00000000000..fc44f264ac1 --- /dev/null +++ b/release/scripts/animation_clean.py @@ -0,0 +1,192 @@ +#!BPY + +""" +Name: 'Clean Animation Curves' +Blender: 249 +Group: 'Animation' +Tooltip: 'Remove unused keyframes for ipo curves' +""" + +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# Copyright (C) 2008-2009: Blender Foundation +# +# 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, +# -------------------------------------------------------------------------- + +import bpy +from Blender import IpoCurve, Draw, Window + +def clean_ipos(ipos): + eul = 0.001 + + def isflat(vec): + prev_y = vec[0][1] + mid_y = vec[1][1] + next_y = vec[2][1] + + # flat status for prev and next + return abs(mid_y-prev_y) < eul, abs(mid_y-next_y) < eul + + + + X=0 + Y=1 + PREV=0 + MID=1 + NEXT=2 + + LEFT = 0 + RIGHT = 1 + + TOT = 0 + TOTBEZ = 0 + # for ipo in bpy.data.ipos: + for ipo in ipos: + if ipo.lib: + continue + # print ipo + for icu in ipo: + interp = icu.interpolation + extend = icu.extend + + bezierPoints = icu.bezierPoints + bezierVecs = [bez.vec for bez in bezierPoints] + + l = len(bezierPoints) + + TOTBEZ += l + + # our aim is to simplify this ipo as much as possible! + if interp == IpoCurve.InterpTypes.BEZIER or interp == interp == IpoCurve.InterpTypes.LINEAR: + #print "Not yet supported" + + if interp == IpoCurve.InterpTypes.BEZIER: + flats = [isflat(bez) for bez in bezierVecs] + else: + # A bit of a waste but fake the locations for these so they will always be flats + # IS better then too much duplicate code. + flats = [(True, True)] * l + for v in bezierVecs: + v[PREV][Y] = v[NEXT][Y] = v[MID][Y] + + + # remove middle points + if l>2: + done_nothing = False + + while not done_nothing and len(bezierVecs) > 2: + done_nothing = True + i = l-2 + + while i > 0: + #print i + #print i, len(bezierVecs) + if flats[i]==(True,True) and flats[i-1][RIGHT] and flats[i+1][LEFT]: + + if abs(bezierVecs[i][MID][Y] - bezierVecs[i-1][MID][Y]) < eul and abs(bezierVecs[i][MID][Y] - bezierVecs[i+1][MID][Y]) < eul: + done_nothing = False + + del flats[i] + del bezierVecs[i] + icu.delBezier(i) + TOT += 1 + l-=1 + i-=1 + + # remove endpoints + if extend == IpoCurve.ExtendTypes.CONST and len(bezierVecs) > 1: + #print l, len(bezierVecs) + # start + + while l > 2 and (flats[0][RIGHT] and flats[1][LEFT] and (abs(bezierVecs[0][MID][Y] - bezierVecs[1][MID][Y]) < eul)): + print "\tremoving 1 point from start of the curve" + del flats[0] + del bezierVecs[0] + icu.delBezier(0) + TOT += 1 + l-=1 + + + # End + while l > 2 and flats[-2][RIGHT] and flats[-1][LEFT] and (abs(bezierVecs[-2][MID][Y] - bezierVecs[-1][MID][Y]) < eul): + print "\tremoving 1 point from end of the curve", l + del flats[l-1] + del bezierVecs[l-1] + icu.delBezier(l-1) + TOT += 1 + l-=1 + + + + if l==2: + if isflat( bezierVecs[0] )[RIGHT] and isflat( bezierVecs[1] )[LEFT] and abs(bezierVecs[0][MID][Y] - bezierVecs[1][MID][Y]) < eul: + # remove the second point + print "\tremoving 1 point from 2 point bez curve" + # remove the second point + del flats[1] + del bezierVecs[1] + icu.delBezier(1) + TOT+=1 + l-=1 + + # Change to linear for faster evaluation + ''' + if l==1: + print 'Linear' + icu.interpolation = IpoCurve.InterpTypes.LINEAR + ''' + + + + + if interp== IpoCurve.InterpTypes.CONST: + print "Not yet supported" + + print 'total', TOT, TOTBEZ + return TOT, TOTBEZ + +def main(): + ret = Draw.PupMenu('Clean Selected Objects Ipos%t|Object IPO%x1|Object Action%x2|%l|All IPOs (be careful!)%x3') + + sce = bpy.data.scenes.active + ipos = [] + + if ret == 3: + ipos.extend(list(bpy.data.ipos)) + else: + for ob in sce.objects.context: + if ret == 1: + ipo = ob.ipo + if ipo: + ipos.append(ipo) + + elif ret == 2: + action = ob.action + if action: + ipos.extend([ipo for ipo in action.getAllChannelIpos().values() if ipo]) + + + + if not ipos: + Draw.PupMenu('Error%t|No ipos found') + else: + total_removed, total = clean_ipos(ipos) + Draw.PupMenu('Done!%t|Removed ' + str(total_removed) + ' of ' + str(total) + ' points') + + Window.RedrawAll() + + +if __name__ == '__main__': + main() diff --git a/release/scripts/image_2d_cutout.py b/release/scripts/image_2d_cutout.py new file mode 100644 index 00000000000..16d0805256b --- /dev/null +++ b/release/scripts/image_2d_cutout.py @@ -0,0 +1,559 @@ +#!BPY + +""" +Name: '2D Cutout Image Importer' +Blender: 249 +Group: 'Image' +Tooltip: 'Batch UV Map images to Planes' +""" + +__author__ = "Kevin Morgan (forTe)" +__url__ = ("Home page, http://gamulabs.freepgs.com") +__version__ = "1.2.1" +__bpydoc__ = """\ +This Script will take an image and +UV map it to a plane sharing the same width to height ratio as the image. +Import options allow for the image to be a still or sequence type image +

+Imports can be single images or whole directories of images depending on the chosen +option. +""" + +#################################################### +#Copyright (C) 2008: Kevin Morgan +#################################################### +#-------------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 3 of the License, or +#(at your option) any later version. +# +#This program is distributed in the hopes 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, see . +#################################################### +#################################################### +#V1.0 +#Basic Functionality +#Published June 28, 2007 +#################################################### +#V1.1 +#Added Support for enabling viewport transparency +#Added more options to the UI for materials +#Added Proportionality code (Pixels per unit) +#Added GPL License Block +#Published June 29, 2007 +#################################################### +#V1.2 +#Added Support for Copying Existing Materials +#Import Images as Sequences +#Refreshed GUI - now with more clutter :( +#Miscellaneous and Housekeeping +#Published June 16, 2008 +#################################################### +#V1.2.1 +#Added Extend Texture Mode option at request of a user +#Published September 24, 2008 +#################################################### + +import Blender +from Blender import BGL, Draw, Image, Mesh, Material, Texture, Window +from Blender.Mathutils import * +import bpy + +# Global Constants +DIR = 0 +SINGLE = 1 +CUROFFS = 0 + +# GUI CONSTANTS +NO_EVT = 0 +SINGLE_IMG = 1 +DIRECTORY_IMG = 2 +CLR_PATH = 3 +CHG_EXT = 4 +EXIT = 5 +DO_SCRIPT = 6 + +VERSIONSTRING = '1.2.1' + +# Note the two parameter dicts could be combined, I just, liked them seperate... +# GUI Buttons Dict +GUIPARAMS = { + 'Path': Draw.Create(''), + 'ImageExt': Draw.Create(''), + 'Seq': Draw.Create(0), + 'PackImage': Draw.Create(0), + 'PPU': Draw.Create(50), + 'VPTransp': Draw.Create(1), + 'XOff': Draw.Create(0.0), + 'YOff': Draw.Create(0.0), + 'ZOff': Draw.Create(0.0), + 'CopyMat': Draw.Create(0), + 'MatId': Draw.Create(0), + 'MatCol': Draw.Create(1.0, 0.0, 0.0), + 'Ref': Draw.Create(0.8), + 'Spec': Draw.Create(0.5), + 'Hard': Draw.Create(50), + 'Alpha': Draw.Create(1.0), + 'ZTransp': Draw.Create(1), + 'Shadeless': Draw.Create(0), + 'TexChan': Draw.Create(1), + 'MPTCol': Draw.Create(1), + 'MPTAlpha': Draw.Create(1), + 'UseAlpha': Draw.Create(1), + 'CalcAlpha': Draw.Create(0), + 'ExtendMode': Draw.Create(0), + 'AutoRefresh': Draw.Create(0), + 'Cyclic': Draw.Create(0), + 'Frames': Draw.Create(100), + 'Offs': Draw.Create(0), + 'StartFr': Draw.Create(1), + 'RedrawImp': Draw.Create(0) +} + +# Script Execution Paramaters +PARAMS = { + 'ImagePaths': [], # Path to images to import + 'ImportType': SINGLE, # Import a Directory or a Single Image? + 'ImageProp': Image.Sources.STILL, # What sources for the image, still or sequence + 'PackImage': 0, # Pack the Image(s)? + 'PPU': 20, # Pixels Per Blender Unit + 'MakeTransp': 1, # Make face transparent in viewport + + 'NewMat': 1, # If true make a new material, otherwise duplicate an existing one, replacing appropriate attributes + 'MaterialId': 0, # ID to take from the Materials list upon copy + 'Materials': None, # Materials in Scene + 'MatProps': {'Col': [1.0, 0.0, 0.0], 'Shadeless': 1, 'Ref': 0.5, 'Spec': 0.5, 'Hard': 200, 'Alpha': 1.0, 'ZTransp': 1}, + + 'TexProps': {'UseAlpha': 1, 'CalcAlpha': 0, 'ExtendMode': 0}, # Texture Properties + 'TexChannel': 0, # Texture Channel + 'TexMapTo': {'Col': 1, 'Alpha': 1}, # Map to Col and/or Alpha + 'SeqProps': {'AutoRefresh': 0, 'Cyclic': 0, 'Frames': 100, 'Offs': 0, 'StartFr': 1}, + 'ObOffset': Vector(1, 0, 0) # Offset by this vector upon creation for multifile import +} + +# Get the Active Scene, of course +scn = bpy.data.scenes.active + +########################################## +# MAIN SCRIPT FUNCTIONS +########################################## + +def imgImport(imgPath): + global CUROFFS, PARAMS + ###################################### + # Load the image + ###################################### + try: + img = Image.Load(imgPath) + imgDimensions = img.getSize() # do this to ensure the data is available + except: + Blender.Draw.PupMenu('Error%t|Unsupported image format for "'+ imgPath.split('\\')[-1].split('/')[-1] +'"') + return + + if PARAMS['PackImage']: + img.pack() + name = Blender.sys.makename(imgPath, strip = 1) + + ###################################### + # Construct the mesh + ###################################### + + me = Mesh.New(name) + + # Calculate Dimensions from Image Size + dim = [float(i)/PARAMS['PPU'] for i in imgDimensions] + v = [[dim[0], dim[1], 0], [-dim[0], dim[1], 0], [-dim[0], -dim[1], 0], [dim[0], -dim[1], 0]] + me.verts.extend(v) + me.faces.extend([0, 1, 2, 3]) + + me.faces[0].image = img + me.faces[0].uv = [Vector(1.0, 1.0), Vector(0.0, 1.0), Vector(0.0, 0.0), Vector(1.0, 0.0)] + + if PARAMS['MakeTransp']: + me.faces[0].transp = Mesh.FaceTranspModes.ALPHA + + ###################################### + # Modify the Material + ###################################### + + mat = None + if not PARAMS['NewMat']: + mat = PARAMS['Materials'][PARAMS['MaterialId']].__copy__() + mat.setName(name) + else: + mat = Material.New(name) + properties = PARAMS['MatProps'] + mat.setRGBCol(properties['Col']) + mat.setRef(properties['Ref']) + mat.setSpec(properties['Spec']) + mat.setHardness(properties['Hard']) + mat.setAlpha(properties['Alpha']) + + if properties['Shadeless']: + mat.mode |= Material.Modes.SHADELESS + if properties['ZTransp']: + mat.mode |= Material.Modes.ZTRANSP + + properties = PARAMS['TexProps'] + + tex = Texture.New(name) + tex.setType('Image') + tex.setImage(img) + if properties['UseAlpha']: + tex.useAlpha = Texture.ImageFlags.USEALPHA + + if properties['CalcAlpha']: + tex.calcAlpha = Texture.ImageFlags.CALCALPHA + + if properties['ExtendMode']: + tex.setExtend('Extend') + + if PARAMS['ImageProp'] == Image.Sources.SEQUENCE: + properties = PARAMS['SeqProps'] + + img.source = PARAMS['ImageProp'] # Needs to be done here, otherwise an error with earlier getSize() + + tex.animStart = properties['StartFr'] + tex.animOffset = properties['Offs'] + tex.animFrames = properties['Frames'] + tex.autoRefresh = properties['AutoRefresh'] + tex.cyclic = properties['Cyclic'] + + texMapSetters = Texture.TexCo.UV + + # PARAMS['TexMapTo']['Col'] (and alpha) will either be 0 or 1 because its from a toggle, otherwise this line doesn't work + texChanSetters = Texture.MapTo.COL * PARAMS['TexMapTo']['Col'] | Texture.MapTo.ALPHA * PARAMS['TexMapTo']['Alpha'] + + mat.setTexture(PARAMS['TexChannel'], tex, texMapSetters, texChanSetters) + me.materials += [mat] + + ###################################### + # Object Construction + ###################################### + + ob = scn.objects.new(me, name) + p = Vector(ob.getLocation()) # Should be the origin, but just to be safe, get it + ob.setLocation((CUROFFS * PARAMS['ObOffset']) + p) + + return + +def translateParams(): + # Translates (or assigns for the most part) GUI values to those that can be read by the + # Import Function + + global GUIPARAMS, PARAMS + + if GUIPARAMS['Seq'].val and PARAMS['ImportType'] != DIR: + PARAMS['ImageProp'] = Image.Sources.SEQUENCE + + PARAMS['PackImage'] = GUIPARAMS['PackImage'].val + PARAMS['PPU'] = GUIPARAMS['PPU'].val + PARAMS['MakeTransp'] = GUIPARAMS['VPTransp'].val + PARAMS['ObOffset'] = Vector(GUIPARAMS['XOff'].val, GUIPARAMS['YOff'].val, GUIPARAMS['ZOff'].val) + + PARAMS['NewMat'] = not GUIPARAMS['CopyMat'].val + PARAMS['MaterialId'] = GUIPARAMS['MatId'].val + PARAMS['MatProps']['Col'] = list(GUIPARAMS['MatCol'].val) + PARAMS['MatProps']['Ref'] = GUIPARAMS['Ref'].val + PARAMS['MatProps']['Spec'] = GUIPARAMS['Spec'].val + PARAMS['MatProps']['Hard'] = GUIPARAMS['Hard'].val + PARAMS['MatProps']['Alpha'] = GUIPARAMS['Alpha'].val + PARAMS['MatProps']['ZTransp'] = GUIPARAMS['ZTransp'].val + PARAMS['MatProps']['Shadeless'] = GUIPARAMS['Shadeless'].val + + PARAMS['TexChannel'] = GUIPARAMS['TexChan'].val - 1 #Channels are 0-9, but GUI shows 1-10 + PARAMS['TexProps']['UseAlpha'] = GUIPARAMS['UseAlpha'].val + PARAMS['TexProps']['CalcAlpha'] = GUIPARAMS['CalcAlpha'].val + PARAMS['TexProps']['ExtendMode'] = GUIPARAMS['ExtendMode'].val + PARAMS['TexMapTo']['Col'] = GUIPARAMS['MPTCol'].val + PARAMS['TexMapTo']['Alpha'] = GUIPARAMS['MPTAlpha'].val + + PARAMS['SeqProps']['AutoRefresh'] = GUIPARAMS['AutoRefresh'].val + PARAMS['SeqProps']['Cyclic'] = GUIPARAMS['Cyclic'].val + PARAMS['SeqProps']['Frames'] = GUIPARAMS['Frames'].val + PARAMS['SeqProps']['Offs'] = GUIPARAMS['Offs'].val + PARAMS['SeqProps']['StartFr'] = GUIPARAMS['StartFr'].val + return + +def doScript(): + # Main script Function + # Consists of choosing between 2 loops, one with a redraw, one without, see comments for why + + global CUROFFS + + translateParams() + + total = len(PARAMS['ImagePaths']) + broken = 0 + + if GUIPARAMS['RedrawImp'].val: # Reduces the need to compare on every go through the loop + for i, path in enumerate(PARAMS['ImagePaths']): + CUROFFS = i # Could be passed to the import Function, but I chose a global instead + Window.DrawProgressBar(float(i)/total, "Importing %i of %i Images..." %(i+1, total)) + imgImport(path) + Blender.Redraw() + if Blender.Get('version') >= 246: + if Window.TestBreak(): + broken = 1 + break + else: + for i, path in enumerate(PARAMS['ImagePaths']): + CUROFFS = i + Window.DrawProgressBar(float(i)/total, "Importing %i of %i Images..." %(i+1, total)) + imgImport(path) + if Blender.Get('version') >= 246: + if Window.TestBreak(): + broken = 1 + break + + if broken: + Window.DrawProgressBar(1.0, "Script Execution Aborted") + else: + Window.DrawProgressBar(1.0, "Finished Importing") + + Blender.Redraw() # Force a refresh, since the user may have chosen to not refresh as they go along + + return + +########################################## +# PATH SETTERS AND CHANGERS +########################################## + +def setSinglePath(filename): + global GUIPARAMS, PARAMS + GUIPARAMS['Path'].val = filename + PARAMS['ImagePaths'] = [filename] + return + +def setDirPath(filename): + global GUIPARAMS, PARAMS + + try: + import os + except: + Draw.PupMenu('Full install of python required to be able to set Directory Paths') + Draw.Exit() + return + + path = os.path.dirname(filename) # Blender.sys.dirname fails on '/' + GUIPARAMS['Path'].val = path + + ext_lower = GUIPARAMS['ImageExt'].val.lower() + for f in os.listdir(path): + if f.lower().endswith(ext_lower): + PARAMS['ImagePaths'].append(os.path.join(path, f)) + + return + +def changeExtension(): + global GUIPARAMS, PARAMS + + if PARAMS['ImportType'] == SINGLE: + return + + try: + import os + except: + Draw.PupMenu('Full install of python required to be able to set Directory Paths') + Draw.Exit() + return + + PARAMS['ImagePaths'] = [] + + ext_lower = GUIPARAMS['ImageExt'].val.lower() + for f in os.listdir(GUIPARAMS['Path'].val): + if f.lower().endswith(ext_lower): + PARAMS['ImagePaths'].append(os.path.join(GUIPARAMS['Path'].val, f)) + + return + +########################################## +# INTERFACE FUNCTIONS +########################################## +def compileMaterialList(): + # Pretty straight forward, just grabs the materials in the blend file and constructs + # an appropriate string for use as a menu + + mats = [mat for mat in bpy.data.materials] + PARAMS['Materials'] = mats + title = 'Materials%t|' + menStrs = [mat.name + '%x' + str(i) + '|' for i, mat in enumerate(mats)] + return title + ''.join(menStrs) + +def event(evt, val): + # Disabled, since Esc is often used from the file browser + #if evt == Draw.ESCKEY: + # Draw.Exit() + + return + +def bevent(evt): + global GUIPARAMS, PARAMS + + if evt == NO_EVT: + Draw.Redraw() + + elif evt == SINGLE_IMG: + Window.FileSelector(setSinglePath, 'Image', Blender.sys.expandpath('//')) + Draw.Redraw() + PARAMS['ImportType'] = SINGLE + + elif evt == DIRECTORY_IMG: + Window.FileSelector(setDirPath, 'Directory', Blender.sys.expandpath('//')) + Draw.Redraw() + PARAMS['ImportType'] = DIR + + elif evt == CLR_PATH: + GUIPARAMS['Path'].val = '' + PARAMS['ImagePaths'] = [] + GUIPARAMS['ImageExt'].val = '' + Draw.Redraw() + + elif evt == CHG_EXT: + changeExtension() + Draw.Redraw() + + elif evt == EXIT: + Draw.Exit() + + elif evt == DO_SCRIPT: + doScript() + + else: + print "ERROR: UNEXPECTED BUTTON EVENT" + + return + +# GUI Colors ###### +ScreenColor = [0.7, 0.7, 0.7] +BackgroundColor = [0.8, 0.8, 0.8] +TitleBG = [0.6, 0.6, 0.6] +TitleCol = [1.0, 1.0, 1.0] +ErrCol = [1.0, 0.0, 0.0] +TextCol = [0.4, 0.4, 0.5] +################### + +def GUI(): + global GUIPARAMS, PARAMS + + BGL.glClearColor(*(ScreenColor + [1.0])) + BGL.glClear(BGL.GL_COLOR_BUFFER_BIT) + + minx = 5 + maxx = 500 + miny = 5 + maxy = 450 + + lineheight = 24 + buPad = 5 # Generic Button Padding, most buttons should have 24-19 (or 5) px space around them + + lP = 5 # Left Padding + rP = 5 # Right Padding + + # Draw Background Box + BGL.glColor3f(*BackgroundColor) + BGL.glRecti(minx, miny, maxx, maxy) + + # Draw Title + BGL.glColor3f(*TitleBG) + BGL.glRecti(minx, maxy - (lineheight), maxx, maxy) + BGL.glColor3f(*TitleCol) + + title = "2D Cutout Image Importer v" + VERSIONSTRING + BGL.glRasterPos2i(minx + lP, maxy - 15) + Draw.Text(title, 'large') + + Draw.PushButton('Exit', EXIT, maxx-50-rP, maxy - lineheight + 2, 50, 19, "Exit Script") + + # Path Buttons + if GUIPARAMS['Path'].val == '': + Draw.PushButton('Single Image', SINGLE_IMG, minx + lP, maxy - (2*lineheight), 150, 19, "Select a Single Image to Import") + Draw.PushButton('Directory', DIRECTORY_IMG, minx + lP + 150, maxy - (2*lineheight), 150, 19, "Select a Directory of Images to Import") + + else: + Draw.PushButton('Clear', CLR_PATH, minx+lP, maxy - (2*lineheight), 50, 19, "Clear Path and Change Import Options") + + GUIPARAMS['Path'] = Draw.String('Path: ', NO_EVT, minx + lP, maxy - (3*lineheight), (maxx-minx-lP-rP), 19, GUIPARAMS['Path'].val, 399, 'Path to Import From') + if PARAMS['ImportType'] == DIR: + GUIPARAMS['ImageExt'] = Draw.String('Image Ext: ', CHG_EXT, minx + lP, maxy - (4*lineheight), 110, 19, GUIPARAMS['ImageExt'].val, 6, 'Image extension for batch directory importing (case insensitive)') + GUIPARAMS['PackImage'] = Draw.Toggle('Pack', NO_EVT, maxx - rP - 50, maxy - (4*lineheight), 50, 19, GUIPARAMS['PackImage'].val, 'Pack Image(s) into .Blend File') + + # Geometry and Viewport Options + BGL.glColor3f(*TextCol) + BGL.glRecti(minx+lP, maxy - (5*lineheight), maxx-rP, maxy - (5*lineheight) + 1) + BGL.glRasterPos2i(minx + lP, maxy-(5*lineheight) + 3) + Draw.Text('Geometry and Display Options', 'small') + + GUIPARAMS['PPU'] = Draw.Slider('Pixels Per Unit: ', NO_EVT, minx + lP, maxy - (6*lineheight), (maxx-minx)/2 - lP, 19, GUIPARAMS['PPU'].val, 1, 5000, 0, 'Set the Number of Pixels Per Blender Unit to preserve Image Size Relations') + GUIPARAMS['VPTransp'] = Draw.Toggle('Viewport Transparency', NO_EVT, minx + lP, maxy - (8*lineheight), (maxx-minx)/2 - lP, 2*lineheight - buPad, GUIPARAMS['VPTransp'].val, 'Display Alpha Transparency in the Viewport') + + GUIPARAMS['XOff'] = Draw.Slider('Offs X: ', NO_EVT, minx + lP + (maxx-minx)/2, maxy - (6*lineheight), (maxx-minx)/2 - lP - rP, 19, GUIPARAMS['XOff'].val, 0, 5.0, 0, 'Amount to Offset Each Imported in the X-Direction if Importing Multiple Images') + GUIPARAMS['YOff'] = Draw.Slider('Offs Y: ', NO_EVT, minx + lP + (maxx-minx)/2, maxy - (7*lineheight), (maxx-minx)/2 - lP - rP, 19, GUIPARAMS['YOff'].val, 0, 5.0, 0, 'Amount to Offset Each Imported in the Y-Direction if Importing Multiple Images') + GUIPARAMS['ZOff'] = Draw.Slider('Offs Z: ', NO_EVT, minx + lP + (maxx-minx)/2, maxy - (8*lineheight), (maxx-minx)/2 - lP - rP, 19, GUIPARAMS['ZOff'].val, 0, 5.0, 0, 'Amount to Offset Each Imported in the Z-Direction if Importing Multiple Images') + + # Material and Texture Options + BGL.glColor3f(*TextCol) + BGL.glRecti(minx+lP, maxy - (9*lineheight), maxx-rP, maxy - (9*lineheight) + 1) + BGL.glRasterPos2i(minx + lP, maxy-(9*lineheight) + 3) + Draw.Text('Material and Texture Options', 'small') + + half = (maxx-minx-lP-rP)/2 + GUIPARAMS['CopyMat'] = Draw.Toggle('Copy Existing Material', NO_EVT, minx + lP, maxy-(10*lineheight), half, 19, GUIPARAMS['CopyMat'].val, 'Copy an Existing Material') + if GUIPARAMS['CopyMat'].val: + menStr = compileMaterialList() + GUIPARAMS['MatId'] = Draw.Menu(menStr, NO_EVT, minx + lP, maxy - (11*lineheight), half, 19, GUIPARAMS['MatId'].val, 'Material to Copy Settings From') + else: + GUIPARAMS['MatCol'] = Draw.ColorPicker(NO_EVT, minx+lP, maxy - (13*lineheight), 40, (3*lineheight) - buPad, GUIPARAMS['MatCol'].val, 'Color of Newly Created Material') + GUIPARAMS['Ref'] = Draw.Slider('Ref: ', NO_EVT, minx +lP+45, maxy - (11*lineheight), half-45, 19, GUIPARAMS['Ref'].val, 0.0, 1.0, 0, 'Set the Ref Value for Created Materials') + GUIPARAMS['Spec'] = Draw.Slider('Spec: ', NO_EVT, minx +lP+45, maxy - (12*lineheight), half-45, 19, GUIPARAMS['Spec'].val, 0.0, 2.0, 0, 'Set the Spec Value for Created Materials') + GUIPARAMS['Hard'] = Draw.Slider('Hard: ', NO_EVT, minx +lP+45, maxy - (13*lineheight), half-45, 19, GUIPARAMS['Hard'].val, 1, 500, 0, 'Set the Hardness Value for Created Materials') + GUIPARAMS['Alpha'] = Draw.Slider('A: ', NO_EVT, minx +lP, maxy - (14*lineheight), half, 19, GUIPARAMS['Alpha'].val, 0.0, 1.0, 0, 'Set the Alpha Value for Created Materials') + + GUIPARAMS['ZTransp'] = Draw.Toggle('ZTransparency', NO_EVT, minx + lP, maxy - (15*lineheight), half, 19, GUIPARAMS['ZTransp'].val, 'Enable ZTransparency') + GUIPARAMS['Shadeless'] = Draw.Toggle('Shadeless', NO_EVT, minx + lP, maxy - (16*lineheight), half, 19, GUIPARAMS['Shadeless'].val, 'Enable Shadeless') + + GUIPARAMS['TexChan'] = Draw.Number('Texture Channel: ', NO_EVT, minx + lP+ half + buPad, maxy - (10*lineheight), half-rP, 19, GUIPARAMS['TexChan'].val, 1, 10, 'Texture Channel for Image Texture') + + GUIPARAMS['MPTCol'] = Draw.Toggle('Color', NO_EVT, minx + lP + half + buPad, maxy - (11*lineheight), half/2, 19, GUIPARAMS['MPTCol'].val, 'Map To Color Channel') + GUIPARAMS['MPTAlpha'] = Draw.Toggle('Alpha', NO_EVT, minx + lP + int((1.5)*half) + buPad, maxy - (11*lineheight), half/2 - rP, 19, GUIPARAMS['MPTAlpha'].val, 'Map To Alpha Channel') + + third = int((maxx-minx-lP-rP)/6) + GUIPARAMS['UseAlpha'] = Draw.Toggle('Use Alpha', NO_EVT, minx + lP + half + buPad, maxy - (12*lineheight), third, 19, GUIPARAMS['UseAlpha'].val, "Use the Images' Alpha Values") + GUIPARAMS['CalcAlpha'] = Draw.Toggle('Calc Alpha', NO_EVT, minx + lP + half + third + buPad, maxy - (12*lineheight), third, 19, GUIPARAMS['CalcAlpha'].val, "Calculate Images' Alpha Values") + GUIPARAMS['ExtendMode'] = Draw.Toggle('Extend', NO_EVT, minx+lP+half+third+third+buPad, maxy - (12*lineheight), third-3, 19, GUIPARAMS['ExtendMode'].val, "Use Extend texture mode. If deselected, Repeat is used") + GUIPARAMS['Seq'] = Draw.Toggle('Sequence', NO_EVT, minx + lP + half + buPad, maxy - (13*lineheight), half-rP, 19, GUIPARAMS['Seq'].val, 'Set the Image(s) to use a Sequence instead of a Still') + + if GUIPARAMS['Seq'].val and not PARAMS['ImportType'] == DIR: + GUIPARAMS['AutoRefresh'] = Draw.Toggle('Auto Refresh', NO_EVT, minx + lP + half + buPad, maxy - (14*lineheight), half/2, 19, GUIPARAMS['AutoRefresh'].val, 'Use Auto Refresh') + GUIPARAMS['Cyclic'] = Draw.Toggle('Cyclic', NO_EVT, minx + lP + half + buPad + half/2, maxy - (14*lineheight), half/2 - rP, 19, GUIPARAMS['Cyclic'].val, 'Repeat Frames Cyclically`') + + GUIPARAMS['Frames'] = Draw.Number('Frames: ', NO_EVT, minx +lP + half + buPad, maxy - (15*lineheight), half - rP, 19, GUIPARAMS['Frames'].val, 1, 30000, 'Sets the Number of Images of a Movie to Use') + GUIPARAMS['Offs'] = Draw.Number('Offs: ', NO_EVT, minx +lP + half + buPad, maxy - (16*lineheight), half/2, 19, GUIPARAMS['Offs'].val, -30000, 30000, 'Offsets the Number of the Frame to use in the Animation') + GUIPARAMS['StartFr'] = Draw.Number('StartFr: ', NO_EVT, minx +lP + half + buPad + half/2, maxy - (16*lineheight), half/2 - rP, 19, GUIPARAMS['StartFr'].val, 1, 30000, 'Sets the Global Starting Frame of the Movie') + elif GUIPARAMS['Seq'].val and PARAMS['ImportType'] == DIR: + BGL.glColor3f(*ErrCol) + BGL.glRasterPos2i(minx + lP + half + buPad + 7, maxy-(14 * lineheight) + 5) + Draw.Text('Sequence only available for Single Image Import', 'small') + + # Import Options + BGL.glColor3f(*TextCol) + BGL.glRecti(minx+lP, maxy - (17*lineheight), maxx-rP, maxy - (17*lineheight) + 1) + BGL.glRasterPos2i(minx + lP, maxy-(17*lineheight) + 3) + Draw.Text('Import', 'small') + + if GUIPARAMS['Path'].val and GUIPARAMS['ImageExt'].val or GUIPARAMS['Path'].val and PARAMS['ImportType'] == SINGLE: + Draw.PushButton('Import', DO_SCRIPT, minx + lP, maxy - (18*lineheight), 75, 19, "Import Image(s)") + else: + BGL.glColor3f(*ErrCol) + BGL.glRasterPos2i(minx+lP, maxy - (18*lineheight) + 5) + Draw.Text('A path and image type must be specified to import images') + + GUIPARAMS['RedrawImp'] = Draw.Toggle('Redraw During Import', NO_EVT, maxx - rP - 150, maxy - (18*lineheight), 150, 19, GUIPARAMS['RedrawImp'].val, 'Redraw the View as Images Import') + +Draw.Register(GUI, event, bevent) \ No newline at end of file diff --git a/release/scripts/object_active_to_other.py b/release/scripts/object_active_to_other.py new file mode 100644 index 00000000000..131d1f63d74 --- /dev/null +++ b/release/scripts/object_active_to_other.py @@ -0,0 +1,58 @@ +#!BPY +""" +Name: 'Copy Active to Selected' +Blender: 249 +Group: 'Object' +Tooltip: 'For every selected object, copy the active to their loc/size/rot' +""" + +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# Script copyright (C) Campbell Barton +# +# 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. +# +# ***** END GPL LICENCE BLOCK ***** +# -------------------------------------------------------------------------- + + +from Blender import Window, sys, Draw +import bpy + +def my_object_util(sce): + ob_act = sce.objects.active + + if not ob_act: + Draw.PupMenu('Error%t|No active object selected') + return + + mats = [ob.matrixWorld for ob in sce.objects.context if ob != ob_act] + + for m in mats: + ob_copy = ob_act.copy() + sce.objects.link(ob_copy) + ob_copy.setMatrix(m) + ob_copy.Layers = ob.Layers + + +def main(): + sce = bpy.data.scenes.active + + Window.WaitCursor(1) + my_object_util(sce) + Window.WaitCursor(0) + +if __name__ == '__main__': + main() diff --git a/release/scripts/scripttemplate_gamelogic_module.py b/release/scripts/scripttemplate_gamelogic_module.py new file mode 100644 index 00000000000..2ef4950917b --- /dev/null +++ b/release/scripts/scripttemplate_gamelogic_module.py @@ -0,0 +1,45 @@ +#!BPY +""" +Name: 'GameLogic Module' +Blender: 249 +Group: 'ScriptTemplate' +Tooltip: 'Basic template for new game logic modules' +""" + +from Blender import Window +import bpy + +script_data = \ +''' +# This module can be accessed by a python controller with +# its execution method set to 'Module' +# * Set the module string to "gamelogic_module.main" (without quotes) +# * When renaming the script it MUST have a .py extension +# * External text modules are supported as long as they are at +# the same location as the blendfile or one of its libraries. + +import GameLogic + +# variables defined here will only be set once when the +# module is first imported. Set object spesific vars +# inside the function if you intend to use the module +# with multiple objects. + +def main(cont): + own = cont.owner + + sens = cont.sensors['mySensor'] + actu = cont.actuators['myActuator'] + + if sens.positive: + cont.activate(actu) + else: + cont.deactivate(actu) + +# dont call main(GameLogic.getCurrentController()), the py controller will +''' + +new_text = bpy.data.texts.new('gamelogic_module.py') +new_text.write(script_data) +bpy.data.texts.active = new_text +Window.RedrawAll() diff --git a/release/scripts/textplugin_convert_ge.py b/release/scripts/textplugin_convert_ge.py new file mode 100644 index 00000000000..f3b44cdb14b --- /dev/null +++ b/release/scripts/textplugin_convert_ge.py @@ -0,0 +1,863 @@ +#!BPY +""" +Name: 'Convert BGE 2.49' +Blender: 246 +Group: 'TextPlugin' +Shortcut: '' +Tooltip: 'Attemps to update deprecated usage of game engine API.' +""" + +# +# Copyright 2009 Alex Fraser +# +# 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 3 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, see . +# + +# +# This script updates game engine scripts that were designed for pre-2.49 +# versions of Blender to run with the new API. Deprecated function calls are +# listed in attributeRenameDict. This script searches for instances of the keys +# in a target script and re-writes them. +# +# Some deprecated functions are complicated to re-write. The most common +# conversions have been implemented, but some have not. Running this will reduce +# the number of deprecation warnings in your scripts, but may not eliminate them +# entirely. +# +# NOTE: The conversion is not guaranteed to be perfect. It is strongly +# recommended that you review all changes after running this script. +# +# TODO: The following attributes are either ambiguous or need special processing +# to handle parameters. Deprecated attributes that map to multiple target +# attributes will require a refactor of the main conversion loop in the +# convert248to249 function: currently, it doesn't allow any conversion to +# advance the row index by more than one. +# +# getLinearVelocity (KX_SCA_AddObjectActuator, KX_ObjectActuator) +# Conflicts with KX_GameObject. +# Maps to multiple attributes. +# setLinearVelocity (KX_SCA_AddObjectActuator, KX_ObjectActuator) +# Conflicts with KX_GameObject. +# Maps to multiple attributes. +# getAngularVelocity (KX_SCA_AddObjectActuator, KX_ObjectActuator) +# Conflicts with KX_GameObject. +# Maps to multiple attributes. +# setAngularVelocity (KX_SCA_AddObjectActuator, KX_ObjectActuator) +# Conflicts with KX_GameObject. +# Maps to multiple attributes. +# setAction (BL_ShapeActionActuator, BL_ActionActuator) +# `reset' argument has no conversion target. +# set (KX_VisibilityActuator, KX_IpoActuator) +# Different numbers of arguments. +# Arguments map to multiple attributes. +# getIndex (SCA_JoystickSensor) +# Incompatible values: Old = 1-based index; new = 0-based. +# getMesh (KX_SCA_ReplaceMeshActuator) +# Return types differ. Need to call object.name. +# getObject (KX_SCA_AddObjectActuator, KX_CameraActuator, +# KX_TrackToActuator, KX_ParentActuator) +# Default return type differs between classes. +# setIndex (SCA_JoystickSensor) +# Incompatible values: Old = 1-based index; new = 0-based. +# setObject (KX_SCA_AddObjectActuator, KX_CameraActuator, +# KX_TrackToActuator, KX_ParentActuator) +# Incompatible types: Old = KX_GameObject or String; new = +# KX_GameObject. +# setOperation (KX_SCA_DynamicActuator, KX_StateActuator) +# Ambiguous: different target names. +# getDRot (KX_ObjectActuator) +# Maps to multiple attributes. +# setDRot (KX_ObjectActuator) +# Arguments map to multiple attributes. +# getDLoc (KX_ObjectActuator) +# Maps to multiple attributes. +# setDLoc (KX_ObjectActuator) +# Arguments map to multiple attributes. +# getTorque (KX_ObjectActuator) +# Maps to multiple attributes. +# setTorque (KX_ObjectActuator) +# Arguments map to multiple attributes. +# getForce (KX_ObjectActuator) +# Maps to multiple attributes. +# setForce (KX_ObjectActuator) +# Arguments map to multiple attributes. +# position (KX_GameObject) +# Conflicts with KX_SoundActuator. +# orientation (KX_GameObject) +# Conflicts with KX_SoundActuator. +# + +import string +import re + +COMMENTCHAR = '#' + +class ParseError(Exception): pass +class ConversionError(Exception): pass + +def findBalancedParens(lines, row, col, openChar = '(', closeChar = ')'): + """Finds a balanced pair of parentheses, searching from lines[row][col]. + The opening parenthesis must be on the starting line. + + Returns two tuples containing the row and column of the opening paren, and + the row and column of the matching paren. + + Throws a ParseError if the first character is not openChar, or if a matching + paren cannot be found.""" + + # + # Find the opening coordinates. + # + oRow = row + oCol = col + line = lines[oRow] + while oCol < len(line): + if line[oCol] == openChar: + break + elif line[oCol] == COMMENTCHAR: + break + oCol = oCol + 1 + + if oCol >= len(line) or line[oCol] != openChar or not re.match(r'^\s*$', line[col:oCol]): + raise ParseError, "Can't find opening parenthesis. '%s'" % openChar + + # + # Find the closing coordinates. + # + eRow = oRow + eCol = oCol + 1 + level = 1 + while eRow < len(lines) and level > 0: + line = lines[eRow] + while eCol < len(line) and level > 0: + c = line[eCol] + if c == openChar: + # Found a nested paren. + level = level + 1 + elif c == closeChar: + # Exiting one level of nesting. + level = level - 1 + if level == 0: + # Back to top level! + return (oRow, oCol), (eRow, eCol) + elif c == COMMENTCHAR: + # Comment. Skip the rest of the line. + break + eCol = eCol + 1 + eRow = eRow + 1 + eCol = 0 + raise ParseError, "Couldn't find closing parenthesis." + +def findLastAssignment(lines, row, attrName): + """Finds the most recent assignment of `attrName' before `row'. Returns + everything after the '=' sign or None, if there was no match.""" + contRegex = re.compile(r'[^#]*?' + # Don't search in comments. + attrName + + r'\s*=\s*(.*)') # Assignment + + cRow = row - 1 + while cRow >= 0: + match = contRegex.search(lines[cRow]) + if match: + return match.group(1) + cRow = cRow - 1 + return None + +def replaceSubstr(s, start, end, newSubStr): + """Replace the contents of `s' between `start' and `end' with + `newSubStr'.""" + return s[:start] + newSubStr + s[end:] + +def replaceNextParens(lines, row, colStart, newOpenChar, newCloseChar, + oldOpenChar = '(', oldCloseChar = ')'): + """Replace the next set of parentheses with different characters. The + opening parenthesis must be located on line `row', and on or after + `colStart'. The closing parenthesis may be on the same line or any following + line. The strings are edited in-place. + + Throws a ParseError if the set of parentheses can't be found. In this case, + the strings in `lines' will be untouched.""" + try: + pOpen, pClose = findBalancedParens(lines, row, colStart, oldOpenChar, + oldCloseChar) + except ParseError: + raise + + # Replacement may change string length. Replace closing paren first. + r, c = pClose + lines[r] = replaceSubstr(lines[r], c, c + 1, newCloseChar) + # Replace opening paren. + r, c = pOpen + lines[r] = replaceSubstr(lines[r], c, c + 1, newOpenChar) + +def replaceSimpleGetter(lines, row, colStart, colEnd, newName): + """Replace a call to a simple getter function with a reference to a + property, e.g. foo.getBar() -> foo.bar + + The function identifier being replaced must be on line `row' and + between `colStart' and `colEnd'. The opening parenthesis must follow + immediately (whitespace is allowed). The closing parenthesis may be on the + same or following lines. + + Throws a ConversionError if the parentheses can't be found. In this case + the content of `lines' will be untouched.""" + try: + replaceNextParens(lines, row, colEnd, newOpenChar = '', newCloseChar = '') + except ParseError: + raise ConversionError, ("Deprecated function reference.") + + lines[row] = replaceSubstr(lines[row], colStart, colEnd, newName) + +def replaceSimpleSetter(lines, row, colStart, colEnd, newName): + """Replace a call to a simple setter function with a reference to a + property, e.g. foo.setBar(baz) -> foo.bar = baz + + The function identifier being replaced must be on line `row' and + between `colStart' and `colEnd'. The opening parenthesis must follow + immediately (whitespace is allowed). The closing parenthesis may be on the + same or following lines. + + Throws a ConversionError if the parentheses can't be found. In this case + the content of `lines' will be untouched.""" + try: + replaceNextParens(lines, row, colEnd, newOpenChar = '', newCloseChar = '') + except ParseError: + raise ConversionError, ("Deprecated function reference.") + + lines[row] = replaceSubstr(lines[row], colStart, colEnd, newName + ' = ') + +def replaceArgsWithListSetter(lines, row, colStart, colEnd, newName): + """Replace a call to a multi-agument setter function with a reference to a + list property, e.g. foo.setBar(baz, bazZ) -> foo.bar = [baz, bazZ] + + The function identifier being replaced must be on line `row' and + between `colStart' and `colEnd'. The opening parenthesis must follow + immediately (whitespace is allowed). The closing parenthesis may be on the + same or following lines. + + Throws a ConversionError if the parentheses can't be found. In this case + the content of `lines' will be untouched.""" + try: + replaceNextParens(lines, row, colEnd, newOpenChar = '[', newCloseChar = ']') + except ParseError: + raise ConversionError, ("Deprecated function reference.") + + lines[row] = replaceSubstr(lines[row], colStart, colEnd, newName + ' = ') + + +def replaceKeyedGetter(lines, row, colStart, colEnd, newName): + """Replace a call to a keyed getter function with a reference to a + property, e.g. foo.getBar(baz) -> foo.bar[baz] + + The function identifier being replaced must be on line `row' and + between `colStart' and `colEnd'. The opening parenthesis must follow + immediately (whitespace is allowed). The closing parenthesis may be on the + same or following lines. + + Throws a ConversionError if the parentheses can't be found. In this case + the content of `lines' will be untouched.""" + try: + replaceNextParens(lines, row, colEnd, newOpenChar = '[', newCloseChar = ']') + except ParseError: + raise ConversionError, ("Deprecated function reference.") + + lines[row] = replaceSubstr(lines[row], colStart, colEnd, newName) + +def replaceGetXYPosition(lines, row, colStart, colEnd, axis): + '''SCA_MouseSensor.getXPosition; SCA_MouseSensor.getYPosition. + This is like a keyed getter, but the key is embedded in the attribute + name. + + Throws a ConversionError if the parentheses can't be found. In this case + the content of `lines' will be untouched.''' + try: + (openRow, openCol), (closeRow, closeCol) = findBalancedParens(lines, + row, colEnd) + except ParseError: + raise ConversionError, "Deprecated function reference." + if closeRow != row: + raise ConversionError, "Can't modify multiple lines." + + lines[row] = replaceSubstr(lines[row], openCol, closeCol + 1, + "[%s]" % axis) + + lines[row] = replaceSubstr(lines[row], colStart, colEnd, 'position') + +def replaceRename(lines, row, colStart, colEnd, newName): + """Replace an identifier with another, e.g. + foo.getBar() -> foo.getBaz() + foo.bar -> foo.baz + + The identifier being replaced must be on line `row' and between `colStart' + and `colEnd'.""" + lines[row] = replaceSubstr(lines[row], colStart, colEnd, newName) + +def replaceAddActiveActuator(lines, row, colStart, colEnd, closure): + '''Extra work needs to be done here to find out the name of the controller, + and whether the actuator should be activated or deactivated. + + Throws a ConversionError if the actuator, controller or condition can't be + found. In this case the content of `lines' will be untouched.''' + try: + (openRow, openCol), (closeRow, closeCol) = findBalancedParens(lines, row, colEnd) + except ParseError: + ConversionError, "Can't find arguments." + + if closeRow != openRow: + raise ConversionError, ("Can't perform conversion: arguments span multiple lines.") + + args = lines[row][openCol + 1:closeCol] + match = re.search(r'([a-zA-Z_]\w*)' # Actuator identifier + r',\s*' + r'([0-9a-zA-Z_]\w*)', # Condition (boolean) + args) + if not match: + raise ConversionError, "Can't find arguments." + + actuator = match.group(1) + condition = match.group(2) + controller = None + + assn = findLastAssignment(lines, row, actuator) + if assn: + match = re.search(r'([a-zA-Z_]\w*)' # Controller identifier + r'\s*\.\s*' # Dot + r'(actuators\s*\[|getActuator\s*\()', # Dictionary/getter identifier + assn) + if match: + controller = match.group(1) + + if not controller: + raise ConversionError, "Can't find actuator's controller." + + gameLogicStart = lines[row].rfind("GameLogic", 0, colStart) + if gameLogicStart < 0: + raise ConversionError, "Can't find GameLogic identifier." + + newExpr = None + if condition in ['1', 'True']: + newExpr = "%s.activate(%s)" % (controller, actuator) + elif condition in ['0', 'False']: + newExpr = "%s.deactivate(%s)" % (controller, actuator) + else: + newExpr = "(lambda: %s and (%s.activate(%s) or True) or %s.deactivate(%s))()" % ( + condition, controller, actuator, controller, actuator) + lines[row] = replaceSubstr(lines[row], gameLogicStart, closeCol + 1, newExpr) + +def getObject(line, attributeStart): + '''Get the object that an attribute belongs to. `attributeStart' is the + index of the first character of the attribute name in the string `line'. + Returns: the identifier preceding `attributeStart', or None if one can't be + found.''' + match = re.search(r'([a-zA-Z_]\w*)\s*\.\s*$', line[0:attributeStart]) + if not match: + return None + return match.group(1) + +def replaceGetActuator(lines, row, colStart, colEnd, closure): + '''getActuator is ambiguous: it could belong to SCA_IController or + SCA_ActuatorSensor. Try to resolve and then convert. + + Raises a ConversionError if the parentheses can't be found, or if the + ambiguity can't be resolved.''' + # Get the name of the object this attribute is attached to. + obName = getObject(lines[row], colStart) + if obName: + # Try to find out whether the object is a controller. + assn = findLastAssignment(lines, row, obName) + if assn and re.search(r'GameLogic\s*\.\s*getCurrentController', assn): + # It is (probably) a controller! + replaceKeyedGetter(lines, row, colStart, colEnd, 'actuators') + return + + raise ConversionError, "Ambiguous: addActiveActuator -> actuators[key] (SCA_IController) or actuator (SCA_ActuatorSensor)." + +def replaceSetOrientation(lines, row, colStart, colEnd, closure): + '''setOrientation is ambiguous: it could belong to KX_SoundActuator or + KX_GameObject. Try to resolve and then convert. If the type can't be + determined, it is assumed to be a KX_GameObject. Currently, only the + conversion for KX_GameObject is implemented. + + Raises a ConversionError if the parentheses can't be found, or if the + object is found to be a KX_SoundActuator.''' + # Get the name of the object this attribute is attached to. + obName = getObject(lines[row], colStart) + if obName: + # Try to find out whether the object is an actuator. + assn = findLastAssignment(lines, row, obName) + if assn: + match = re.search(r'([a-zA-Z_]\w*)' # Controller identifier + r'\s*\.\s*' # Dot + r'(actuators\s*\[|getActuator\s*\()', # Dictionary/getter identifier + assn) + if match: + # It's probably a KX_SoundActuator. + raise ConversionError, "Not implemented: Can't convert arguments to matrix." + + # It's probably a KX_GameObject. + replaceSimpleSetter(lines, row, colStart, colEnd, 'localOrientation') + +def replaceSetPosition(lines, row, colStart, colEnd, closure): + '''setPosition is ambiguous: it could belong to KX_SoundActuator or + KX_GameObject. Try to resolve and then convert. If the type can't be + determined, it is assumed to be a KX_GameObject. + + Raises a ConversionError if the parentheses can't be found.''' + # Get the name of the object this attribute is attached to. + obName = getObject(lines[row], colStart) + if obName: + # Try to find out whether the object is an actuator. + assn = findLastAssignment(lines, row, obName) + if assn: + match = re.search(r'([a-zA-Z_]\w*)' # Controller identifier + r'\s*\.\s*' # Dot + r'(actuators\s*\[|getActuator\s*\()', # Dictionary/getter identifier + assn) + if match: + # It's probably a KX_SoundActuator. + replaceSimpleSetter(lines, row, colStart, colEnd, 'position') + + # It's probably a KX_GameObject. + replaceSimpleSetter(lines, row, colStart, colEnd, 'localPosition') + +def replaceSplitProperty(lines, row, colStart, colEnd, (newGetter, newSetter)): + '''Some property attributes behave differently when being written to or read + from. Try to determine the operation, and replace accordingly. E.G. + o.position = foo -> o.localPosition = foo # set + foo = o.position -> foo = o.worldPosition # get + + This implementation can not handle cases where the object is returned from + a function, e.g. + foo = bar.getObject().position # Error! + + Raises a ConversionError if the operation can't be determined, or if the + object is returned from a function.''' + assnRegex = re.compile(r'(=\s*)?' # Getter + r'[a-zA-Z_]\w*' # Object identifier + r'\.([a-zA-Z_][a-zA-Z0-9_.]*)+' # Trailing attributes + r'(\s*=)?') # Setter + match = assnRegex.search(lines[row]) + + if not match: + raise ConversionError, "Can't determine operation (getting or setting)." + + setting = False + getting = False + if match.group(1): + getting = True + if match.group(3): + setting = True + if (getting and setting) or ((not getting) and (not setting)): + raise ConversionError, "Can't determine operation (getting or setting)." + + if getting: + replaceRename(lines, row, colStart, colEnd, newGetter) + else: + replaceRename(lines, row, colStart, colEnd, newSetter) + +def notImplemented(lines, row, colStart, colEnd, classNames): + message = "Conversion not implemented. See documentation for " +\ + string.join(classNames, ', ') + raise ConversionError, message + +# +# Deprecated attribute information. The format is: +# deprecatedAttributeName: (conversionFunction, closure) +# Usually the closure will be the name of the superceding attribute. +# +# Since each deprecated attribute can appear in this dictionary only once, it is +# the conversion function's responsibility to resolve ambiguity. +# +attributeRenameDict = { + # Special cases + 'addActiveActuator': (replaceAddActiveActuator, None), # + 'getActuator': (replaceGetActuator, None), # SCA_IController, SCA_ActuatorSensor + 'getXPosition': (replaceGetXYPosition, '0'), # SCA_MouseSensor + 'getYPosition': (replaceGetXYPosition, '1'), # SCA_MouseSensor + 'setOrientation': (replaceSetOrientation, None), # KX_GameObject, KX_SoundActuator + 'setPosition': (replaceSetPosition, None), # KX_GameObject, KX_SoundActuator + + # Keyed getters/setters + 'getSensor': (replaceKeyedGetter, 'sensors'), # SCA_IController + + # Multi-arg -> List setter + 'setAxis': (replaceArgsWithListSetter, 'axis'), # SCA_JoystickSensor + 'setForceLimitX': (replaceArgsWithListSetter, 'forceLimitX'), # KX_ObjectActuator + 'setForceLimitY': (replaceArgsWithListSetter, 'forceLimitY'), # KX_ObjectActuator + 'setForceLimitZ': (replaceArgsWithListSetter, 'forceLimitZ'), # KX_ObjectActuator + 'setHat': (replaceArgsWithListSetter, 'hat'), # SCA_JoystickSensor + 'setPID': (replaceArgsWithListSetter, 'pid'), # KX_ObjectActuator + 'setVelocity': (replaceArgsWithListSetter, 'velocity'), # KX_SoundActuator + + # Straight rename + 'getButtonValue': (replaceRename, 'getButtonActiveList'), # SCA_JoystickSensor + + # Split properties + 'scaling': (replaceSplitProperty, ('worldScaling', 'localScaling')), # KX_GameObject + + # Simple getters/setters + 'getSensors': (replaceSimpleGetter, 'sensors'), # SCA_IController + 'getActuators': (replaceSimpleGetter, 'actuators'), # SCA_IController + 'enableViewport': (replaceSimpleSetter, 'useViewport'), # KX_Camera + 'getAction': (replaceSimpleGetter, 'action'), # BL_ShapeActionActuator, BL_ActionActuator + 'getAxis': (replaceSimpleGetter, 'axis'), # SCA_JoystickSensor + 'getAxisValue': (replaceSimpleGetter, 'axisValues'), # SCA_JoystickSensor + 'getBlendin': (replaceSimpleGetter, 'blendIn'), # BL_ShapeActionActuator, BL_ActionActuator + 'getBodies': (replaceSimpleGetter, 'bodies'), # KX_NetworkMessageSensor + 'getButton': (replaceSimpleGetter, 'button'), # SCA_JoystickSensor + 'getCamera': (replaceSimpleGetter, 'camera'), # KX_SceneActuator + 'getConeOrigin': (replaceSimpleGetter, 'coneOrigin'), # KX_RadarSensor + 'getConeTarget': (replaceSimpleGetter, 'coneTarget'), # KX_RadarSensor + 'getContinue': (replaceSimpleGetter, 'useContinue'), # BL_ActionActuator + 'getCurrentlyPressedKeys': (replaceSimpleGetter, 'events'), # SCA_KeyboardSensor + 'getDamping': (replaceSimpleGetter, 'damping'), # KX_ObjectActuator + 'getDelay': (replaceSimpleGetter, 'delay'), # SCA_DelaySensor + 'getDistribution': (replaceSimpleGetter, 'distribution'), # SCA_RandomActuator + 'getDuration': (replaceSimpleGetter, 'duration'), # SCA_DelaySensor + 'getEnd': (replaceSimpleGetter, 'frameEnd'), # BL_ShapeActionActuator, KX_IpoActuator, BL_ActionActuator + 'getExecutePriority': (replaceSimpleGetter, 'executePriority'), # SCA_ILogicBrick + 'getFile': (replaceSimpleGetter, 'fileName'), # KX_GameActuator + 'getFilename': (replaceSimpleGetter, 'fileName'), # KX_SoundActuator + 'getForceIpoActsLocal': (replaceSimpleGetter, 'useIpoLocal'), # KX_IpoActuator + 'getForceLimitX': (replaceSimpleGetter, 'forceLimitX'), # KX_ObjectActuator + 'getForceLimitY': (replaceSimpleGetter, 'forceLimitY'), # KX_ObjectActuator + 'getForceLimitZ': (replaceSimpleGetter, 'forceLimitZ'), # KX_ObjectActuator + 'getFrame': (replaceSimpleGetter, 'frame'), # BL_ShapeActionActuator, BL_ActionActuator + 'getFrameMessageCount': (replaceSimpleGetter, 'frameMessageCount'), # KX_NetworkMessageSensor + 'getFrameProperty': (replaceSimpleGetter, 'framePropName'), # BL_ShapeActionActuator, BL_ActionActuator + 'getFrequency': (replaceSimpleGetter, 'frequency'), # SCA_ISensor + 'getGain': (replaceSimpleGetter, 'volume'), # KX_SoundActuator, KX_CDActuator + 'getHat': (replaceSimpleGetter, 'hat'), # SCA_JoystickSensor + 'getHeight': (replaceSimpleGetter, 'height'), # KX_CameraActuator + 'getHitNormal': (replaceSimpleGetter, 'hitNormal'), # KX_MouseFocusSensor, KX_RaySensor + 'getHitObject': (replaceSimpleGetter, 'hitObject'), # KX_MouseFocusSensor, KX_RaySensor, KX_TouchSensor + 'getHitObjectList': (replaceSimpleGetter, 'hitObjectList'), # KX_TouchSensor + 'getHitPosition': (replaceSimpleGetter, 'hitPosition'), # KX_MouseFocusSensor, KX_RaySensor + 'getHold1': (replaceSimpleGetter, 'hold1'), # SCA_KeyboardSensor + 'getHold2': (replaceSimpleGetter, 'hold2'), # SCA_KeyboardSensor + 'getInvert': (replaceSimpleGetter, 'invert'), # SCA_ISensor + 'getIpoAdd': (replaceSimpleGetter, 'useIpoAdd'), # KX_IpoActuator + 'getIpoAsForce': (replaceSimpleGetter, 'useIpoAsForce'), # KX_IpoActuator + 'getKey': (replaceSimpleGetter, 'key'), # SCA_KeyboardSensor + 'getLastCreatedObject': (replaceSimpleGetter, 'objectLastCreated'), # KX_SCA_AddObjectActuator + 'getLevel': (replaceSimpleGetter, 'level'), # SCA_ISensor + 'getLightList': (replaceSimpleGetter, 'lights'), # KX_Scene + 'getLooping': (replaceSimpleGetter, 'looping'), # KX_SoundActuator + 'getMass': (replaceSimpleGetter, 'mass'), # KX_GameObject + 'getMax': (replaceSimpleGetter, 'max'), # KX_CameraActuator + 'getMin': (replaceSimpleGetter, 'min'), # KX_CameraActuator + 'getName': (replaceSimpleGetter, 'name'), # KX_Scene + 'getNumAxes': (replaceSimpleGetter, 'numAxis'), # SCA_JoystickSensor + 'getNumButtons': (replaceSimpleGetter, 'numButtons'), # SCA_JoystickSensor + 'getNumHats': (replaceSimpleGetter, 'numHats'), # SCA_JoystickSensor + 'getObjectList': (replaceSimpleGetter, 'objects'), # KX_Scene + 'getOperation': (replaceSimpleGetter, 'mode'), # KX_SCA_DynamicActuator + 'getOrientation': (replaceSimpleGetter, 'worldOrientation'), # KX_GameObject + 'getOwner': (replaceSimpleGetter, 'owner'), # SCA_ILogicBrick + 'getPara1': (replaceSimpleGetter, 'para1'), # SCA_RandomActuator + 'getPara2': (replaceSimpleGetter, 'para2'), # SCA_RandomActuator + 'getParent': (replaceSimpleGetter, 'parent'), # KX_GameObject + 'getPID': (replaceSimpleGetter, 'pid'), # KX_ObjectActuator + 'getPitch': (replaceSimpleGetter, 'pitch'), # KX_SoundActuator + 'getPosition': (replaceSimpleGetter, 'worldPosition'), # KX_GameObject + 'getPressedKeys': (replaceSimpleGetter, 'events'), # SCA_KeyboardSensor + 'getPriority': (replaceSimpleGetter, 'priority'), # BL_ShapeActionActuator, BL_ActionActuator + 'getProjectionMatrix': (replaceSimpleGetter, 'projection_matrix'), # KX_Camera + 'getProperty': (replaceSimpleGetter, 'propName'), # SCA_PropertySensor, SCA_RandomActuator, SCA_PropertyActuator + 'getRayDirection': (replaceSimpleGetter, 'rayDirection'), # KX_MouseFocusSensor, KX_RaySensor + 'getRaySource': (replaceSimpleGetter, 'raySource'), # KX_MouseFocusSensor + 'getRayTarget': (replaceSimpleGetter, 'rayTarget'), # KX_MouseFocusSensor + 'getRepeat': (replaceSimpleGetter, 'repeat'), # SCA_DelaySensor + 'getRollOffFactor': (replaceSimpleGetter, 'rollOffFactor'), # KX_SoundActuator + 'getScene': (replaceSimpleGetter, 'scene'), # KX_SceneActuator + 'getScript': (replaceSimpleGetter, 'script'), # SCA_PythonController + 'getSeed': (replaceSimpleGetter, 'seed'), # SCA_RandomActuator + 'getStart': (replaceSimpleGetter, 'frameStart'), # BL_ShapeActionActuator, KX_IpoActuator, BL_ActionActuator + 'getState': (replaceSimpleGetter, 'state'), # SCA_IController, KX_GameObject + 'getSubject': (replaceSimpleGetter, 'subject'), # KX_NetworkMessageSensor + 'getSubjects': (replaceSimpleGetter, 'subjects'), # KX_NetworkMessageSensor + 'getThreshold': (replaceSimpleGetter, 'threshold'), # SCA_JoystickSensor + 'getTime': (replaceSimpleGetter, 'time'), # KX_SCA_AddObjectActuator, KX_TrackToActuator + 'getTouchMaterial': (replaceSimpleGetter, 'useMaterial'), # KX_TouchSensor + 'getType': (replaceSimpleGetter, 'mode'), # SCA_PropertySensor + 'getUse3D': (replaceSimpleGetter, 'use3D'), # KX_TrackToActuator + 'getUseNegPulseMode': (replaceSimpleGetter, 'useNegPulseMode'), # SCA_ISensor + 'getUsePosPulseMode': (replaceSimpleGetter, 'usePosPulseMode'), # SCA_ISensor + 'getUseRestart': (replaceSimpleGetter, 'useRestart'), # KX_SceneActuator + 'getValue': (replaceSimpleGetter, 'value'), # SCA_PropertySensor, SCA_PropertyActuator + 'getVisible': (replaceSimpleGetter, 'visible'), # KX_GameObject + 'getXY': (replaceSimpleGetter, 'useXY'), # KX_CameraActuator + 'isConnected': (replaceSimpleGetter, 'connected'), # SCA_JoystickSensor + 'isPositive': (replaceSimpleGetter, 'positive'), # SCA_ISensor + 'isTriggered': (replaceSimpleGetter, 'triggered'), # SCA_ISensor + 'setActuator': (replaceSimpleSetter, 'actuator'), # SCA_ActuatorSensor + 'setBlendin': (replaceSimpleSetter, 'blendIn'), # BL_ShapeActionActuator, BL_ActionActuator + 'setBlendtime': (replaceSimpleSetter, 'blendTime'), # BL_ShapeActionActuator, BL_ActionActuator + 'setBodyType': (replaceSimpleSetter, 'usePropBody'), # KX_NetworkMessageActuator + 'setBody': (replaceSimpleSetter, 'body'), # KX_NetworkMessageActuator + 'setButton': (replaceSimpleSetter, 'button'), # SCA_JoystickSensor + 'setCamera': (replaceSimpleSetter, 'camera'), # KX_SceneActuator + 'setContinue': (replaceSimpleSetter, 'useContinue'), # BL_ActionActuator + 'setDamping': (replaceSimpleSetter, 'damping'), # KX_ObjectActuator + 'setDelay': (replaceSimpleSetter, 'delay'), # SCA_DelaySensor + 'setDuration': (replaceSimpleSetter, 'duration'), # SCA_DelaySensor + 'setEnd': (replaceSimpleSetter, 'frameEnd'), # BL_ShapeActionActuator, KX_IpoActuator, BL_ActionActuator + 'setExecutePriority': (replaceSimpleSetter, 'executePriority'), # SCA_ILogicBrick + 'setFile': (replaceSimpleSetter, 'fileName'), # KX_GameActuator + 'setFilename': (replaceSimpleSetter, 'fileName'), # KX_SoundActuator + 'setForceIpoActsLocal': (replaceSimpleSetter, 'useIpoLocal'), # KX_IpoActuator + 'setFrame': (replaceSimpleSetter, 'frame'), # BL_ShapeActionActuator, BL_ActionActuator + 'setFrameProperty': (replaceSimpleSetter, 'framePropName'), # BL_ShapeActionActuator, BL_ActionActuator + 'setFrequency': (replaceSimpleSetter, 'frequency'), # SCA_ISensor + 'setGain': (replaceSimpleSetter, 'volume'), # KX_SoundActuator, KX_CDActuator + 'setHeight': (replaceSimpleSetter, 'height'), # KX_CameraActuator + 'setHold1': (replaceSimpleSetter, 'hold1'), # SCA_KeyboardSensor + 'setHold2': (replaceSimpleSetter, 'hold2'), # SCA_KeyboardSensor + 'setInvert': (replaceSimpleSetter, 'invert'), # SCA_ISensor + 'setIpoAdd': (replaceSimpleSetter, 'useIpoAdd'), # KX_IpoActuator + 'setIpoAsForce': (replaceSimpleSetter, 'useIpoAsForce'), # KX_IpoActuator + 'setKey': (replaceSimpleSetter, 'key'), # SCA_KeyboardSensor + 'setLevel': (replaceSimpleSetter, 'level'), # SCA_ISensor + 'setLooping': (replaceSimpleSetter, 'looping'), # KX_SoundActuator + 'setMask': (replaceSimpleSetter, 'mask'), # KX_StateActuator + 'setMax': (replaceSimpleSetter, 'max'), # KX_CameraActuator + 'setMesh': (replaceSimpleSetter, 'mesh'), # KX_SCA_ReplaceMeshActuator + 'setMin': (replaceSimpleSetter, 'min'), # KX_CameraActuator + 'setPitch': (replaceSimpleSetter, 'pitch'), # KX_SoundActuator + 'setPriority': (replaceSimpleSetter, 'priority'), # BL_ShapeActionActuator, BL_ActionActuator + 'setProjectionMatrix': (replaceSimpleSetter, 'projection_matrix'), # KX_Camera + 'setProperty': (replaceSimpleSetter, 'propName'), # KX_IpoActuator, SCA_PropertySensor, SCA_RandomActuator, SCA_PropertyActuator + 'setRepeat': (replaceSimpleSetter, 'repeat'), # SCA_DelaySensor + 'setRollOffFactor': (replaceSimpleSetter, 'rollOffFactor'), # KX_SoundActuator + 'setScene': (replaceSimpleSetter, 'scene'), # KX_SceneActuator + 'setScript': (replaceSimpleSetter, 'script'), # SCA_PythonController + 'setSeed': (replaceSimpleSetter, 'seed'), # SCA_RandomActuator + 'setStart': (replaceSimpleSetter, 'frameStart'), # BL_ShapeActionActuator, KX_IpoActuator, BL_ActionActuator + 'setState': (replaceSimpleSetter, 'state'), # KX_GameObject + 'setSubject': (replaceSimpleSetter, 'subject'), # KX_NetworkMessageActuator + 'setSubjectFilterText': (replaceSimpleSetter, 'subject'), # KX_NetworkMessageSensor + 'setThreshold': (replaceSimpleSetter, 'threshold'), # SCA_JoystickSensor + 'setTime': (replaceSimpleSetter, 'time'), # KX_SCA_AddObjectActuator, KX_TrackToActuator + 'setToPropName': (replaceSimpleSetter, 'propName'), # KX_NetworkMessageActuator + 'setType': (replaceSimpleSetter, 'mode'), # SCA_PropertySensor + 'setUse3D': (replaceSimpleSetter, 'use3D'), # KX_TrackToActuator + 'setUseNegPulseMode': (replaceSimpleSetter, 'useNegPulseMode'), # SCA_ISensor + 'setUsePosPulseMode': (replaceSimpleSetter, 'usePosPulseMode'), # SCA_ISensor + 'setUseRestart': (replaceSimpleSetter, 'useRestart'), # KX_SceneActuator + 'setValue': (replaceSimpleSetter, 'value'), # SCA_PropertySensor, SCA_PropertyActuator + 'setXY': (replaceSimpleSetter, 'useXY'), # KX_CameraActuator + + # Unimplemented! + 'getLinearVelocity': (notImplemented, ['KX_SCA_AddObjectActuator', 'KX_GameObject']), + 'setLinearVelocity': (notImplemented, ['KX_SCA_AddObjectActuator', 'KX_GameObject']), + 'getAngularVelocity': (notImplemented, ['KX_SCA_AddObjectActuator', 'KX_GameObject']), + 'setAngularVelocity': (notImplemented, ['KX_SCA_AddObjectActuator', 'KX_GameObject']), + 'setAction': (notImplemented, ['BL_ShapeActionActuator', 'BL_ActionActuator']), + 'set': (notImplemented, ['KX_VisibilityActuator', 'KX_IpoActuator']), + 'getIndex': (notImplemented, ['SCA_JoystickSensor']), + 'getMesh': (notImplemented, ['KX_SCA_ReplaceMeshActuator']), + 'getObject': (notImplemented, ['KX_SCA_AddObjectActuator', 'KX_CameraActuator', 'KX_TrackToActuator', 'KX_ParentActuator']), + 'setIndex': (notImplemented, ['SCA_JoystickSensor']), + 'setObject': (notImplemented, ['KX_SCA_AddObjectActuator', 'KX_CameraActuator', 'KX_TrackToActuator', 'KX_ParentActuator']), + 'setOperation': (notImplemented, ['KX_SCA_DynamicActuator', 'KX_StateActuator']), + 'position': (notImplemented, ['KX_GameObject', 'KX_SoundActuator']), + 'orientation': (notImplemented, ['KX_GameObject', 'KX_SoundActuator']), + 'getDRot': (notImplemented, ['KX_ObjectActuator']), + 'setDRot': (notImplemented, ['KX_ObjectActuator']), + 'getDLoc': (notImplemented, ['KX_ObjectActuator']), + 'setDLoc': (notImplemented, ['KX_ObjectActuator']), + 'getTorque': (notImplemented, ['KX_ObjectActuator']), + 'getTorque': (notImplemented, ['KX_ObjectActuator']), + 'getForce': (notImplemented, ['KX_ObjectActuator']), + 'setForce': (notImplemented, ['KX_ObjectActuator']), +} + +def convert248to249(lines, log = True, logErrors = True, fileName = None): + # Regular expression for finding attributes. For the string 'a.b', this + # returns three groups: ['a.b', 'a.', 'b']. The last is the attribute name. + attrRegex = re.compile(r'\.\s*' # Dot + r'([a-zA-Z_]\w*)') # Identifier + + fileIdStr = "" + if fileName: + fileIdStr = fileName + ": " + row = 0 + col = 0 + nconverted = 0 + nerrors = 0 + while row < len(lines): + originalLine = lines[row] + changed = False + while col < len(lines[row]): + # Don't search past comment. We have to check each iteration + # because the line contents may have changed. + commentStart = lines[row].find('#', col) + if commentStart < 0: + commentStart = len(lines[row]) + + # Search for an attribute identifier. + match = attrRegex.search(lines[row], col, commentStart) + if not match: + break + + attrName = match.group(1) + if attributeRenameDict.has_key(attrName): + # name is deprecated. + func, closure = attributeRenameDict[attrName] + try: + # Convert! + func(lines, row, match.start(1), match.end(1), closure) + except ConversionError as e: + # Insert a comment saying the conversion failed. + print "ERROR: %sline %d, %s: %s\n" % ( + fileIdStr, row + 1, attrName, e) + if logErrors: + lines.insert(row, + "##248## ERROR: %s: %s\n" % + (attrName, e)) + row = row + 1 + nerrors = nerrors + 1 + else: + changed = True + nconverted = nconverted + 1 + # Search the rest of this line. + col = match.start(1) + + if changed and log: + # Insert a comment to showing difference in lines. + if originalLine[-1] != '\n': + originalLine = originalLine + '\n' + lines.insert(row, "##248##%s" % originalLine) + row = row + 1 + + row = row + 1 + col = 0 + return nconverted, nerrors + +def usage(): + print "Usage: blender248to249.py [options] [outfile]" + print "Options:" + print "\t--nolog Don't include old lines as comments." + print "\t--quieterrors Don't insert errors as comments." + +def runAsConsoleScript(): + '''Called when being run as a console script.''' + try: + opts, args = getopt.getopt(sys.argv[1:], "", ["nolog", "quieterrors"]) + except getopt.GetoptError, err: + # print help information and exit: + print str(err) + usage() + sys.exit(2) + + log = True + logErrors = True + for o, a in opts: + if o == "--nolog": + log = False + elif o == "--quieterrors": + logErrors = False + + try: + inpath = args.pop(0) + except IndexError: + usage() + sys.exit(2) + try: + outpath = args.pop(0) + except IndexError: + outpath = inpath + + infile = io.FileIO(inpath, 'r') + # arbitrary file size of around 100kB + lines = infile.readlines(100000) + infile.close() + + nconverted, nerrors = convert248to249(lines, log, logErrors) + + outfile = io.FileIO(outpath, 'w') + outfile.writelines(lines) + outfile.close() + print "Conversion finished. Modified %d attributes." % nconverted + print "There were %d errors." % nerrors + print "Please review all the changes." + +def runAsTextPlugin(): + '''Called when run as a text plugin.''' + + import Blender + from Blender import Window, sys, Draw + import BPyTextPlugin, bpy + + message = ("Convert Game Engine script from 4.48 API to 2.49 API%t|" + "Run on active script only%x1|" + "Run on ALL text buffers%x2") + convertAllBuffers = Draw.PupMenu(message) == 2 + + Window.WaitCursor(1) + try: + nconverted = 0 + nerrors = 0 + + if convertAllBuffers: + texts = bpy.data.texts + else: + if not bpy.data.texts.active: + Draw.PupMenu("No active buffer.") + return + texts = [bpy.data.texts.active] + + Blender.SaveUndoState('Convert BGE 2.49') + + for txt in texts: + bufName = txt.name + if txt.lib: + bufName = txt.lib + '/' + bufName + lines = txt.asLines() + for i in range(0, len(lines)): + if not lines[i].endswith('\n'): + lines[i] = lines[i] + '\n' + + nc, ne = convert248to249(lines, fileName = bufName) + nconverted = nconverted + nc + nerrors = nerrors + ne + txt.clear() + for line in lines: + txt.write(line) + + finally: + Window.WaitCursor(0) + + message = "Converted %d attributes." % nconverted + if nerrors == 1: + message = message + " There was 1 error (see console)." + if nerrors > 1: + message = message + " There were %d errors (see console)." % nerrors + message = message + "|Please review all the changes." + Draw.PupMenu(message) + +def main(): + try: + import Blender + except ImportError: + runAsConsoleScript() + else: + runAsTextPlugin() + +# This lets you import the script without running it +if __name__ == "__main__": + import sys + import getopt + import io + main() diff --git a/release/scripts/wizard_bolt_factory.py b/release/scripts/wizard_bolt_factory.py new file mode 100644 index 00000000000..6a280eccc58 --- /dev/null +++ b/release/scripts/wizard_bolt_factory.py @@ -0,0 +1,2804 @@ +#!BPY +# -*- coding: latin-1 -*- +""" +Name: 'Bolt Factory' +Blender: 248 +Group: 'Wizards' +Tooltip: 'Create models of various types of screw fasteners.' +""" + +__author__ = " Aaron Keith (Spudmn) " +__version__ = "2.00 2009/05/22" +__url__ = ["Author's site,http://sourceforge.net/projects/boltfactory/", "Blender,http://wiki.blender.org/index.php/Extensions:Py/Scripts/Manual/Misc/Bolt_Factory"] +__bpydoc__ = """\ +Bolt_Factory.py + +Bolt Factory is a Python script for Blender 3D. + +The script allows the user to create models of various types of screw fasteners. + +For best results set the material to smooth and apply a Edge Split modifier +with default settings. + + +History: + +V2.00 22/05/09 by Aaron Keith + +- Better error checking. +- Lock Nut and Hex Nut meshes added. +- Pre-sets for common metric bolts and nuts. +- Improved GUI. +- Meshes scaled to a smaller size +- Fixed bug when using crest and root percent other than 10% +- Can now create meshes in Edit Mode. This will add to the + current mesh and align with the current view. + +V1.00 01/04/08 by Aaron Keith + +- This version is very much a work in progress. +- This is my first attempt to program in Python. This version is + unpolished and doesn't do much error checking. Therefore + if the user sets strange variable the model created will be + as equally strange. + +- To Do: +- Better error checking. +- More Head and Bit types. +- Better documentation. + + +""" + +# -------------------------------------------------------------------------- +# Bolt_Factory.py +# -------------------------------------------------------------------------- +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# Copyright (C) 2009: Aaron Keith +# +# 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. +# +# ***** END GPL LICENCE BLOCK ***** +# -------------------------------------------------------------------------- + + + + +import Blender +from Blender import Draw, BGL,Mesh +from Blender import * +from math import * +from Blender import Mathutils +from Blender.Mathutils import * + + +#Global_Scale = 0.001 #1 blender unit = X mm +Global_Scale = 0.1 #1 blender unit = X mm +#Global_Scale = 1.0 #1 blender unit = X mm +Global_NutRad = 0.0 +MAX_INPUT_NUMBER = 50 + +No_Event,On_Preset_Click,On_Apply_Click,On_Create_Click,On_Hex_Click, On_Cap_Click,On_Dome_Click,On_Pan_Click,On_Bit_None_Click,On_Bit_Allen_Click,On_Bit_Philips_Click,On_Exit_Click,On_Model_Bolt_Click,On_Model_Nut_Click,On_Hex_Nut_Click,On_Lock_Nut_Click,On_Test_Click = range(17) # this is like a ENUM + + +Head_Type={'HEX' : [Draw.Create(1),On_Hex_Click,""], + 'CAP' : [Draw.Create(0),On_Cap_Click,""], + 'DOME': [Draw.Create(0),On_Dome_Click,""], + 'PAN' : [Draw.Create(0),On_Pan_Click,""]} + + +Bit_Type={'NONE' : [Draw.Create(1),On_Bit_None_Click,""], + 'ALLEN' : [Draw.Create(0),On_Bit_Allen_Click,""], + 'PHILLIPS': [Draw.Create(0),On_Bit_Philips_Click,""]} + +Model_Type={'BOLT' : [Draw.Create(1),On_Model_Bolt_Click,"Bolt Settings"], + 'NUT' : [Draw.Create(0),On_Model_Nut_Click,"Nut Settings"]} + +Nut_Type={'HEX' : [Draw.Create(1),On_Hex_Nut_Click,""], + 'LOCK' : [Draw.Create(0),On_Lock_Nut_Click,""]} + + +Phillips_Bit_Depth = Draw.Create(3.27) +Philips_Bit_Dia = Draw.Create(5.20) + +Allen_Bit_Depth = Draw.Create(4.0) +Allen_Bit_Flat_Distance = Draw.Create(6.0) + +Hex_Head_Height = Draw.Create(5.3) +Hex_Head_Flat_Distance = Draw.Create(13.0) + +Cap_Head_Dia = Draw.Create(13.5) +Cap_Head_Height = Draw.Create(8.0) + +Dome_Head_Dia = Draw.Create(16.0) + +Pan_Head_Dia = Draw.Create(16.0) + +Shank_Dia = Draw.Create(8.0) +Shank_Length = Draw.Create(0.0) + +Thread_Length = Draw.Create(16.0) +Major_Dia = Draw.Create(8.0) +Minor_Dia = Draw.Create(6.917) +Pitch = Draw.Create(1.0) +Crest_Percent = Draw.Create(10) +Root_Percent = Draw.Create(10) + +Hex_Nut_Height = Draw.Create(8.0) +Hex_Nut_Flat_Distance = Draw.Create(13.0) + +Preset_Menu = Draw.Create(5) + + +########################################################################################## +########################################################################################## +## Miscellaneous Utilities +########################################################################################## +########################################################################################## + +# Returns a list of verts rotated by the given matrix. Used by SpinDup +def Rot_Mesh(verts,matrix): + return [list(Vector(v) * matrix) for v in verts] + +# Returns a list of faces that has there index incremented by offset +def Copy_Faces(faces,offset): + ret = [] + for f in faces: + fsub = [] + for i in range(len(f)): + fsub.append(f[i]+ offset) + ret.append(fsub) + return ret + + +# Much like Blenders built in SpinDup. +def SpinDup(VERTS,FACES,DEGREE,DIVISIONS,AXIS): + verts=[] + faces=[] + + if DIVISIONS == 0: + DIVISIONS = 1 + + step = DEGREE/DIVISIONS # set step so pieces * step = degrees in arc + + for i in xrange(int(DIVISIONS)): + rotmat = Mathutils.RotationMatrix(step*i, 4, AXIS) # 4x4 rotation matrix, 30d about the x axis. + Rot = Rot_Mesh(VERTS,rotmat) + faces.extend(Copy_Faces(FACES,len(verts))) + verts.extend(Rot) + return verts,faces + + +# Returns a list of verts that have been moved up the z axis by DISTANCE +def Move_Verts_Up_Z(VERTS,DISTANCE): + return [[v[0],v[1],v[2]+DISTANCE] for v in VERTS] + + +# Returns a list of verts and faces that has been mirrored in the AXIS +def Mirror_Verts_Faces(VERTS,FACES,AXIS,FLIP_POINT =0): + ret_vert = [] + ret_face = [] + offset = len(VERTS) + if AXIS == 'y': + for v in VERTS: + Delta = v[0] - FLIP_POINT + ret_vert.append([FLIP_POINT-Delta,v[1],v[2]]) + if AXIS == 'x': + for v in VERTS: + Delta = v[1] - FLIP_POINT + ret_vert.append([v[0],FLIP_POINT-Delta,v[2]]) + if AXIS == 'z': + for v in VERTS: + Delta = v[2] - FLIP_POINT + ret_vert.append([v[0],v[1],FLIP_POINT-Delta]) + + for f in FACES: + fsub = [] + for i in range(len(f)): + fsub.append(f[i]+ offset) + fsub.reverse() # flip the order to make norm point out + ret_face.append(fsub) + + return ret_vert,ret_face + + + +# Returns a list of faces that +# make up an array of 4 point polygon. +def Build_Face_List_Quads(OFFSET,COLUM,ROW,FLIP = 0): + Ret =[] + RowStart = 0; + for j in range(ROW): + for i in range(COLUM): + Res1 = RowStart + i; + Res2 = RowStart + i + (COLUM +1) + Res3 = RowStart + i + (COLUM +1) +1 + Res4 = RowStart+i+1 + if FLIP: + Ret.append([OFFSET+Res1,OFFSET+Res2,OFFSET+Res3,OFFSET+Res4]) + else: + Ret.append([OFFSET+Res4,OFFSET+Res3,OFFSET+Res2,OFFSET+Res1]) + RowStart += COLUM+1 + return Ret + + +# Returns a list of faces that makes up a fill pattern for a +# circle +def Fill_Ring_Face(OFFSET,NUM,FACE_DOWN = 0): + Ret =[] + Face = [1,2,0] + TempFace = [0,0,0] + A = 0 + B = 1 + C = 2 + if NUM < 3: + return None + for i in range(NUM-2): + if (i%2): + TempFace[0] = Face[C]; + TempFace[1] = Face[C] + 1; + TempFace[2] = Face[B]; + if FACE_DOWN: + Ret.append([OFFSET+Face[2],OFFSET+Face[1],OFFSET+Face[0]]) + else: + Ret.append([OFFSET+Face[0],OFFSET+Face[1],OFFSET+Face[2]]) + else: + TempFace[0] =Face[C]; + if Face[C] == 0: + TempFace[1] = NUM-1; + else: + TempFace[1] = Face[C] - 1; + TempFace[2] = Face[B]; + if FACE_DOWN: + Ret.append([OFFSET+Face[0],OFFSET+Face[1],OFFSET+Face[2]]) + else: + Ret.append([OFFSET+Face[2],OFFSET+Face[1],OFFSET+Face[0]]) + + Face[0] = TempFace[0] + Face[1] = TempFace[1] + Face[2] = TempFace[2] + return Ret + + +########################################################################################## +########################################################################################## +## Converter Functions For Bolt Factory +########################################################################################## +########################################################################################## + + +def Flat_To_Radius(FLAT): + h = (float(FLAT)/2)/cos(radians(30)) + return h + +def Get_Phillips_Bit_Height(Bit_Dia): + Flat_Width_half = (Bit_Dia*(0.5/1.82))/2.0 + Bit_Rad = Bit_Dia / 2.0 + x = Bit_Rad - Flat_Width_half + y = tan(radians(60))*x + return y + +########################################################################################## +########################################################################################## +## Error Checking +########################################################################################## +########################################################################################## + + +def Error_Check(): + + #global Phillips_Bit_Depth + #global Philips_Bit_Dia + + #global Allen_Bit_Depth + #global Allen_Bit_Flat_Distance + + #global Hex_Head_Height + #global Hex_Head_Flat_Distance + + #global Cap_Head_Dia + #global Cap_Head_Height + + + #global Dome_Head_Dia + + #global Pan_Head_Dia + + #global Shank_Dia + #global Shank_Length + + global Thread_Length + global Major_Dia + global Minor_Dia + global Pitch + global Hex_Nut_Flat_Distance + global Model_Type + #global Crest_Percent + #global Root_Percent + + Error_Result = 0 + + if Minor_Dia.val >= Major_Dia.val: + error_txt = "Error%t|Major Dia must be larger than Minor Dia" + Blender.Draw.PupMenu(error_txt) + print error_txt + Error_Result = TRUE + + elif (Model_Type['BOLT'][0].val) and ((Pitch.val*7.0) > Thread_Length.val): + error_txt = "Error%t|Thread length must be at least 7 times the Pitch" + Blender.Draw.PupMenu(error_txt) + print error_txt + Error_Result = TRUE + + elif (Model_Type['NUT'][0].val) and (Hex_Nut_Flat_Distance.val < Major_Dia.val): + error_txt = "Error%t|Nut Flat Distance must be greater than Major Dia" + Blender.Draw.PupMenu(error_txt) + print error_txt + Error_Result = TRUE + + elif (Model_Type['NUT'][0].val) and ((Pitch.val * 2.5 )> Hex_Nut_Height.val): + error_txt = "Error%t|Nut Height must be greater than 2.5 * Pitch" + Blender.Draw.PupMenu(error_txt) + print error_txt + Error_Result = TRUE + + elif (Model_Type['BOLT'][0].val): + Check_Head_Height = None + Check_Bit_Height = None + if (Bit_Type['ALLEN'][0].val): + Check_Bit_Height = Allen_Bit_Depth.val + if (Bit_Type['PHILLIPS'][0].val): + Check_Bit_Height = Phillips_Bit_Depth.val + if (Head_Type['HEX'][0].val): + Check_Head_Height = Hex_Head_Height.val + if (Head_Type['CAP'][0].val): + Check_Head_Height = Cap_Head_Height.val + + if Check_Head_Height != None and Check_Bit_Height != None : + if Check_Bit_Height > Check_Head_Height: + error_txt = "Error%t|Bit Depth must not be greater that Head Height" + Blender.Draw.PupMenu(error_txt) + print error_txt + Error_Result = TRUE + + + return Error_Result + + + +########################################################################################## +########################################################################################## +## Create Allen Bit +########################################################################################## +########################################################################################## + + +def Allen_Fill(OFFSET,FLIP= 0): + faces = [] + Lookup = [[19,1,0], + [19,2,1], + [19,3,2], + [19,20,3], + [20,4,3], + [20,5,4], + [20,6,5], + [20,7,6], + [20,8,7], + [20,9,8], + + [20,21,9], + + [21,10,9], + [21,11,10], + [21,12,11], + [21,13,12], + [21,14,13], + [21,15,14], + + [21,22,15], + [22,16,15], + [22,17,16], + [22,18,17] + ] + for i in Lookup: + if FLIP: + faces.append([OFFSET+i[2],OFFSET+i[1],OFFSET+i[0]]) + else: + faces.append([OFFSET+i[0],OFFSET+i[1],OFFSET+i[2]]) + + return faces + +def Allen_Bit_Dia(FLAT_DISTANCE): + Flat_Radius = (float(FLAT_DISTANCE)/2.0)/cos(radians(30)) + return (Flat_Radius * 1.05) * 2.0 + +def Allen_Bit_Dia_To_Flat(DIA): + Flat_Radius = (DIA/2.0)/1.05 + return (Flat_Radius * cos (radians(30)))* 2.0 + + + +def Create_Allen_Bit(FLAT_DISTANCE,HEIGHT): + Div = 36 + verts = [] + faces = [] + + Flat_Radius = (float(FLAT_DISTANCE)/2.0)/cos(radians(30)) + OUTTER_RADIUS = Flat_Radius * 1.05 + Outter_Radius_Height = Flat_Radius * (0.1/5.77) + FaceStart_Outside = len(verts) + Deg_Step = 360.0 /float(Div) + + for i in range((Div/2)+1): # only do half and mirror later + x = sin(radians(i*Deg_Step))*OUTTER_RADIUS + y = cos(radians(i*Deg_Step))*OUTTER_RADIUS + verts.append([x,y,0]) + + FaceStart_Inside = len(verts) + + Deg_Step = 360.0 /float(6) + for i in range((6/2)+1): + x = sin(radians(i*Deg_Step))* Flat_Radius + y = cos(radians(i*Deg_Step))* Flat_Radius + verts.append([x,y,0-Outter_Radius_Height]) + + faces.extend(Allen_Fill(FaceStart_Outside,0)) + + + FaceStart_Bottom = len(verts) + + Deg_Step = 360.0 /float(6) + for i in range((6/2)+1): + x = sin(radians(i*Deg_Step))* Flat_Radius + y = cos(radians(i*Deg_Step))* Flat_Radius + verts.append([x,y,0-HEIGHT]) + + faces.extend(Build_Face_List_Quads(FaceStart_Inside,3,1,TRUE)) + faces.extend(Fill_Ring_Face(FaceStart_Bottom,4)) + + + M_Verts,M_Faces = Mirror_Verts_Faces(verts,faces,'y') + verts.extend(M_Verts) + faces.extend(M_Faces) + + return verts,faces,OUTTER_RADIUS * 2.0 + + +########################################################################################## +########################################################################################## +## Create Phillips Bit +########################################################################################## +########################################################################################## + + +def Phillips_Fill(OFFSET,FLIP= 0): + faces = [] + Lookup = [[0,1,10], + [1,11,10], + [1,2,11], + [2,12,11], + + [2,3,12], + [3,4,12], + [4,5,12], + [5,6,12], + [6,7,12], + + [7,13,12], + [7,8,13], + [8,14,13], + [8,9,14], + + + [10,11,16,15], + [11,12,16], + [12,13,16], + [13,14,17,16], + [15,16,17,18] + + + ] + for i in Lookup: + if FLIP: + if len(i) == 3: + faces.append([OFFSET+i[2],OFFSET+i[1],OFFSET+i[0]]) + else: + faces.append([OFFSET+i[3],OFFSET+i[2],OFFSET+i[1],OFFSET+i[0]]) + else: + if len(i) == 3: + faces.append([OFFSET+i[0],OFFSET+i[1],OFFSET+i[2]]) + else: + faces.append([OFFSET+i[0],OFFSET+i[1],OFFSET+i[2],OFFSET+i[3]]) + return faces + + + +def Create_Phillips_Bit(FLAT_DIA,FLAT_WIDTH,HEIGHT): + Div = 36 + verts = [] + faces = [] + + FLAT_RADIUS = FLAT_DIA * 0.5 + OUTTER_RADIUS = FLAT_RADIUS * 1.05 + + Flat_Half = float(FLAT_WIDTH)/2.0 + + FaceStart_Outside = len(verts) + Deg_Step = 360.0 /float(Div) + for i in range((Div/4)+1): # only do half and mirror later + x = sin(radians(i*Deg_Step))*OUTTER_RADIUS + y = cos(radians(i*Deg_Step))*OUTTER_RADIUS + verts.append([x,y,0]) + + + FaceStart_Inside = len(verts) + verts.append([0,FLAT_RADIUS,0]) #10 + verts.append([Flat_Half,FLAT_RADIUS,0]) #11 + verts.append([Flat_Half,Flat_Half,0]) #12 + verts.append([FLAT_RADIUS,Flat_Half,0]) #13 + verts.append([FLAT_RADIUS,0,0]) #14 + + + verts.append([0,Flat_Half,0-HEIGHT]) #15 + verts.append([Flat_Half,Flat_Half,0-HEIGHT]) #16 + verts.append([Flat_Half,0,0-HEIGHT]) #17 + + verts.append([0,0,0-HEIGHT]) #18 + + faces.extend(Phillips_Fill(FaceStart_Outside,TRUE)) + + Spin_Verts,Spin_Face = SpinDup(verts,faces,360,4,'z') + + return Spin_Verts,Spin_Face,OUTTER_RADIUS * 2 + + +########################################################################################## +########################################################################################## +## Create Head Types +########################################################################################## +########################################################################################## + +def Max_Pan_Bit_Dia(HEAD_DIA): + HEAD_RADIUS = HEAD_DIA * 0.5 + XRad = HEAD_RADIUS * 1.976 + return (sin(radians(10))*XRad) * 2.0 + + +def Create_Pan_Head(HOLE_DIA,HEAD_DIA,SHANK_DIA,HEIGHT,RAD1,RAD2,FACE_OFFSET): + + DIV = 36 + HOLE_RADIUS = HOLE_DIA * 0.5 + HEAD_RADIUS = HEAD_DIA * 0.5 + SHANK_RADIUS = SHANK_DIA * 0.5 + + verts = [] + faces = [] + Row = 0 + BEVEL = HEIGHT * 0.01 + #Dome_Rad = HEAD_RADIUS * (1.0/1.75) + + Dome_Rad = HEAD_RADIUS * 1.12 + RAD_Offset = HEAD_RADIUS * 0.96 + OtherRad = HEAD_RADIUS * 0.16 + OtherRad_X_Offset = HEAD_RADIUS * 0.84 + OtherRad_Z_Offset = HEAD_RADIUS * 0.504 + XRad = HEAD_RADIUS * 1.976 + ZRad = HEAD_RADIUS * 1.768 + EndRad = HEAD_RADIUS * 0.284 + EndZOffset = HEAD_RADIUS * 0.432 + HEIGHT = HEAD_RADIUS * 0.59 + +# Dome_Rad = 5.6 +# RAD_Offset = 4.9 +# OtherRad = 0.8 +# OtherRad_X_Offset = 4.2 +# OtherRad_Z_Offset = 2.52 +# XRad = 9.88 +# ZRad = 8.84 +# EndRad = 1.42 +# EndZOffset = 2.16 +# HEIGHT = 2.95 + + FaceStart = FACE_OFFSET + + z = cos(radians(10))*ZRad + verts.append([HOLE_RADIUS,0.0,(0.0-ZRad)+z]) + Start_Height = 0 - ((0.0-ZRad)+z) + Row += 1 + + #for i in range(0,30,10): was 0 to 30 more work needed to make this look good. + for i in range(10,30,10): + x = sin(radians(i))*XRad + z = cos(radians(i))*ZRad + verts.append([x,0.0,(0.0-ZRad)+z]) + Row += 1 + + for i in range(20,140,10): + x = sin(radians(i))*EndRad + z = cos(radians(i))*EndRad + if ((0.0 - EndZOffset)+z) < (0.0-HEIGHT): + verts.append([(HEAD_RADIUS -EndRad)+x,0.0,0.0 - HEIGHT]) + else: + verts.append([(HEAD_RADIUS -EndRad)+x,0.0,(0.0 - EndZOffset)+z]) + Row += 1 + + + verts.append([SHANK_RADIUS,0.0,(0.0-HEIGHT)]) + Row += 1 + + verts.append([SHANK_RADIUS,0.0,(0.0-HEIGHT)-Start_Height]) + Row += 1 + + + sVerts,sFaces = SpinDup(verts,faces,360,DIV,'z') + sVerts.extend(verts) #add the start verts to the Spin verts to complete the loop + + faces.extend(Build_Face_List_Quads(FaceStart,Row-1,DIV)) + + Global_Head_Height = HEIGHT ; + + + return Move_Verts_Up_Z(sVerts,Start_Height),faces,HEIGHT + + + +def Create_Dome_Head(HOLE_DIA,HEAD_DIA,SHANK_DIA,HEIGHT,RAD1,RAD2,FACE_OFFSET): + DIV = 36 + HOLE_RADIUS = HOLE_DIA * 0.5 + HEAD_RADIUS = HEAD_DIA * 0.5 + SHANK_RADIUS = SHANK_DIA * 0.5 + + verts = [] + faces = [] + Row = 0 + BEVEL = HEIGHT * 0.01 + #Dome_Rad = HEAD_RADIUS * (1.0/1.75) + + Dome_Rad = HEAD_RADIUS * 1.12 + #Head_Height = HEAD_RADIUS * 0.78 + RAD_Offset = HEAD_RADIUS * 0.98 + Dome_Height = HEAD_RADIUS * 0.64 + OtherRad = HEAD_RADIUS * 0.16 + OtherRad_X_Offset = HEAD_RADIUS * 0.84 + OtherRad_Z_Offset = HEAD_RADIUS * 0.504 + + +# Dome_Rad = 5.6 +# RAD_Offset = 4.9 +# Dome_Height = 3.2 +# OtherRad = 0.8 +# OtherRad_X_Offset = 4.2 +# OtherRad_Z_Offset = 2.52 +# + + FaceStart = FACE_OFFSET + + verts.append([HOLE_RADIUS,0.0,0.0]) + Row += 1 + + + for i in range(0,60,10): + x = sin(radians(i))*Dome_Rad + z = cos(radians(i))*Dome_Rad + if ((0.0-RAD_Offset)+z) <= 0: + verts.append([x,0.0,(0.0-RAD_Offset)+z]) + Row += 1 + + + for i in range(60,160,10): + x = sin(radians(i))*OtherRad + z = cos(radians(i))*OtherRad + z = (0.0-OtherRad_Z_Offset)+z + if z < (0.0-Dome_Height): + z = (0.0-Dome_Height) + verts.append([OtherRad_X_Offset+x,0.0,z]) + Row += 1 + + verts.append([SHANK_RADIUS,0.0,(0.0-Dome_Height)]) + Row += 1 + + + sVerts,sFaces = SpinDup(verts,faces,360,DIV,'z') + sVerts.extend(verts) #add the start verts to the Spin verts to complete the loop + + faces.extend(Build_Face_List_Quads(FaceStart,Row-1,DIV)) + + return sVerts,faces,Dome_Height + + + +def Create_Cap_Head(HOLE_DIA,HEAD_DIA,SHANK_DIA,HEIGHT,RAD1,RAD2): + DIV = 36 + + HOLE_RADIUS = HOLE_DIA * 0.5 + HEAD_RADIUS = HEAD_DIA * 0.5 + SHANK_RADIUS = SHANK_DIA * 0.5 + + verts = [] + faces = [] + Row = 0 + BEVEL = HEIGHT * 0.01 + + + FaceStart = len(verts) + + verts.append([HOLE_RADIUS,0.0,0.0]) + Row += 1 + + #rad + + for i in range(0,100,10): + x = sin(radians(i))*RAD1 + z = cos(radians(i))*RAD1 + verts.append([(HEAD_RADIUS-RAD1)+x,0.0,(0.0-RAD1)+z]) + Row += 1 + + + verts.append([HEAD_RADIUS,0.0,0.0-HEIGHT+BEVEL]) + Row += 1 + + verts.append([HEAD_RADIUS-BEVEL,0.0,0.0-HEIGHT]) + Row += 1 + + #rad2 + + for i in range(0,100,10): + x = sin(radians(i))*RAD2 + z = cos(radians(i))*RAD2 + verts.append([(SHANK_RADIUS+RAD2)-x,0.0,(0.0-HEIGHT-RAD2)+z]) + Row += 1 + + + sVerts,sFaces = SpinDup(verts,faces,360,DIV,'z') + sVerts.extend(verts) #add the start verts to the Spin verts to complete the loop + + + faces.extend(Build_Face_List_Quads(FaceStart,Row-1,DIV)) + + return sVerts,faces,HEIGHT+RAD2 + + + +def Create_Hex_Head(FLAT,HOLE_DIA,SHANK_DIA,HEIGHT): + + verts = [] + faces = [] + HOLE_RADIUS = HOLE_DIA * 0.5 + Half_Flat = FLAT/2 + TopBevelRadius = Half_Flat - (Half_Flat* (0.05/8)) + Undercut_Height = (Half_Flat* (0.05/8)) + Shank_Bevel = (Half_Flat* (0.05/8)) + Flat_Height = HEIGHT - Undercut_Height - Shank_Bevel + #Undercut_Height = 5 + SHANK_RADIUS = SHANK_DIA/2 + Row = 0; + + verts.append([0.0,0.0,0.0]) + + + FaceStart = len(verts) + #inner hole + + x = sin(radians(0))*HOLE_RADIUS + y = cos(radians(0))*HOLE_RADIUS + verts.append([x,y,0.0]) + + + x = sin(radians(60/6))*HOLE_RADIUS + y = cos(radians(60/6))*HOLE_RADIUS + verts.append([x,y,0.0]) + + + x = sin(radians(60/3))*HOLE_RADIUS + y = cos(radians(60/3))*HOLE_RADIUS + verts.append([x,y,0.0]) + + + x = sin(radians(60/2))*HOLE_RADIUS + y = cos(radians(60/2))*HOLE_RADIUS + verts.append([x,y,0.0]) + Row += 1 + + #bevel + + x = sin(radians(0))*TopBevelRadius + y = cos(radians(0))*TopBevelRadius + vec1 = Mathutils.Vector([x,y,0.0]) + verts.append([x,y,0.0]) + + + x = sin(radians(60/6))*TopBevelRadius + y = cos(radians(60/6))*TopBevelRadius + vec2 = Mathutils.Vector([x,y,0.0]) + verts.append([x,y,0.0]) + + + x = sin(radians(60/3))*TopBevelRadius + y = cos(radians(60/3))*TopBevelRadius + vec3 = Mathutils.Vector([x,y,0.0]) + verts.append([x,y,0.0]) + + + x = sin(radians(60/2))*TopBevelRadius + y = cos(radians(60/2))*TopBevelRadius + vec4 = Mathutils.Vector([x,y,0.0]) + verts.append([x,y,0.0]) + Row += 1 + + #Flats + + x = tan(radians(0))*Half_Flat + dvec = vec1 - Mathutils.Vector([x,Half_Flat,0.0]) + verts.append([x,Half_Flat,-dvec.length]) + + + x = tan(radians(60/6))*Half_Flat + dvec = vec2 - Mathutils.Vector([x,Half_Flat,0.0]) + verts.append([x,Half_Flat,-dvec.length]) + + + x = tan(radians(60/3))*Half_Flat + dvec = vec3 - Mathutils.Vector([x,Half_Flat,0.0]) + Lowest_Point = -dvec.length + verts.append([x,Half_Flat,-dvec.length]) + + + x = tan(radians(60/2))*Half_Flat + dvec = vec4 - Mathutils.Vector([x,Half_Flat,0.0]) + Lowest_Point = -dvec.length + verts.append([x,Half_Flat,-dvec.length]) + Row += 1 + + #down Bits Tri + x = tan(radians(0))*Half_Flat + verts.append([x,Half_Flat,Lowest_Point]) + + x = tan(radians(60/6))*Half_Flat + verts.append([x,Half_Flat,Lowest_Point]) + + x = tan(radians(60/3))*Half_Flat + verts.append([x,Half_Flat,Lowest_Point]) + + x = tan(radians(60/2))*Half_Flat + verts.append([x,Half_Flat,Lowest_Point]) + Row += 1 + + #down Bits + + x = tan(radians(0))*Half_Flat + verts.append([x,Half_Flat,-Flat_Height]) + + x = tan(radians(60/6))*Half_Flat + verts.append([x,Half_Flat,-Flat_Height]) + + x = tan(radians(60/3))*Half_Flat + verts.append([x,Half_Flat,-Flat_Height]) + + x = tan(radians(60/2))*Half_Flat + verts.append([x,Half_Flat,-Flat_Height]) + Row += 1 + + + #under cut + + x = sin(radians(0))*Half_Flat + y = cos(radians(0))*Half_Flat + vec1 = Mathutils.Vector([x,y,0.0]) + verts.append([x,y,-Flat_Height]) + + x = sin(radians(60/6))*Half_Flat + y = cos(radians(60/6))*Half_Flat + vec2 = Mathutils.Vector([x,y,0.0]) + verts.append([x,y,-Flat_Height]) + + x = sin(radians(60/3))*Half_Flat + y = cos(radians(60/3))*Half_Flat + vec3 = Mathutils.Vector([x,y,0.0]) + verts.append([x,y,-Flat_Height]) + + x = sin(radians(60/2))*Half_Flat + y = cos(radians(60/2))*Half_Flat + vec3 = Mathutils.Vector([x,y,0.0]) + verts.append([x,y,-Flat_Height]) + Row += 1 + + #under cut down bit + x = sin(radians(0))*Half_Flat + y = cos(radians(0))*Half_Flat + vec1 = Mathutils.Vector([x,y,0.0]) + verts.append([x,y,-Flat_Height-Undercut_Height]) + + x = sin(radians(60/6))*Half_Flat + y = cos(radians(60/6))*Half_Flat + vec2 = Mathutils.Vector([x,y,0.0]) + verts.append([x,y,-Flat_Height-Undercut_Height]) + + x = sin(radians(60/3))*Half_Flat + y = cos(radians(60/3))*Half_Flat + vec3 = Mathutils.Vector([x,y,0.0]) + verts.append([x,y,-Flat_Height-Undercut_Height]) + + x = sin(radians(60/2))*Half_Flat + y = cos(radians(60/2))*Half_Flat + vec3 = Mathutils.Vector([x,y,0.0]) + verts.append([x,y,-Flat_Height-Undercut_Height]) + Row += 1 + + #under cut to Shank BEVEAL + x = sin(radians(0))*(SHANK_RADIUS+Shank_Bevel) + y = cos(radians(0))*(SHANK_RADIUS+Shank_Bevel) + vec1 = Mathutils.Vector([x,y,0.0]) + verts.append([x,y,-Flat_Height-Undercut_Height]) + + x = sin(radians(60/6))*(SHANK_RADIUS+Shank_Bevel) + y = cos(radians(60/6))*(SHANK_RADIUS+Shank_Bevel) + vec2 = Mathutils.Vector([x,y,0.0]) + verts.append([x,y,-Flat_Height-Undercut_Height]) + + x = sin(radians(60/3))*(SHANK_RADIUS+Shank_Bevel) + y = cos(radians(60/3))*(SHANK_RADIUS+Shank_Bevel) + vec3 = Mathutils.Vector([x,y,0.0]) + verts.append([x,y,-Flat_Height-Undercut_Height]) + + x = sin(radians(60/2))*(SHANK_RADIUS+Shank_Bevel) + y = cos(radians(60/2))*(SHANK_RADIUS+Shank_Bevel) + vec3 = Mathutils.Vector([x,y,0.0]) + verts.append([x,y,-Flat_Height-Undercut_Height]) + Row += 1 + + #under cut to Shank BEVEAL + x = sin(radians(0))*SHANK_RADIUS + y = cos(radians(0))*SHANK_RADIUS + vec1 = Mathutils.Vector([x,y,0.0]) + verts.append([x,y,-Flat_Height-Undercut_Height-Shank_Bevel]) + + x = sin(radians(60/6))*SHANK_RADIUS + y = cos(radians(60/6))*SHANK_RADIUS + vec2 = Mathutils.Vector([x,y,0.0]) + verts.append([x,y,-Flat_Height-Undercut_Height-Shank_Bevel]) + + x = sin(radians(60/3))*SHANK_RADIUS + y = cos(radians(60/3))*SHANK_RADIUS + vec3 = Mathutils.Vector([x,y,0.0]) + verts.append([x,y,-Flat_Height-Undercut_Height-Shank_Bevel]) + + x = sin(radians(60/2))*SHANK_RADIUS + y = cos(radians(60/2))*SHANK_RADIUS + vec3 = Mathutils.Vector([x,y,0.0]) + verts.append([x,y,-Flat_Height-Undercut_Height-Shank_Bevel]) + Row += 1 + + + #Global_Head_Height = 0 - (-HEIGHT-0.1) + faces.extend(Build_Face_List_Quads(FaceStart,3,Row - 1)) + + + Mirror_Verts,Mirror_Faces = Mirror_Verts_Faces(verts,faces,'y') + verts.extend(Mirror_Verts) + faces.extend(Mirror_Faces) + + Spin_Verts,Spin_Faces = SpinDup(verts,faces,360,6,'z') + + return Spin_Verts,Spin_Faces,0 - (-HEIGHT) + + +########################################################################################## +########################################################################################## +## Create Bolt +########################################################################################## +########################################################################################## + + + +def MakeBolt(): + global Phillips_Bit_Depth + global Philips_Bit_Dia + + global Allen_Bit_Depth + global Allen_Bit_Flat_Distance + + global Hex_Head_Height + global Hex_Head_Flat_Distance + + global Cap_Head_Dia + global Cap_Head_Height + + + global Dome_Head_Dia + + global Pan_Head_Dia + + global Shank_Dia + global Shank_Length + + global Thread_Length + global Major_Dia + global Minor_Dia + global Pitch + global Crest_Percent + global Root_Percent + + verts = [] + faces = [] + Bit_Verts = [] + Bit_Faces = [] + Bit_Dia = 0.001 + Head_Verts = [] + Head_Faces= [] + Head_Height = 0.0 + ReSized_Allen_Bit_Flat_Distance = Allen_Bit_Flat_Distance.val # set default + + + Head_Height = Hex_Head_Height.val # will be changed by the Head Functions + + if Bit_Type['ALLEN'][0].val and Head_Type['PAN'][0].val: + #need to size Allen bit if it is too big. + if Allen_Bit_Dia(Allen_Bit_Flat_Distance.val) > Max_Pan_Bit_Dia(Pan_Head_Dia.val): + ReSized_Allen_Bit_Flat_Distance = Allen_Bit_Dia_To_Flat(Max_Pan_Bit_Dia(Pan_Head_Dia.val)) * 1.05 + print "Resized Allen Bit Flat Distance to ",ReSized_Allen_Bit_Flat_Distance + + #bit Mesh + if Bit_Type['ALLEN'][0].val: + Bit_Verts,Bit_Faces,Bit_Dia = Create_Allen_Bit(ReSized_Allen_Bit_Flat_Distance,Allen_Bit_Depth.val) + + if Bit_Type['PHILLIPS'][0].val: + Bit_Verts,Bit_Faces,Bit_Dia = Create_Phillips_Bit(Philips_Bit_Dia.val,Philips_Bit_Dia.val*(0.5/1.82),Phillips_Bit_Depth.val) + + + #Head Mesh + if Head_Type['HEX'][0].val: + Head_Verts,Head_Faces,Head_Height = Create_Hex_Head(Hex_Head_Flat_Distance.val,Bit_Dia,Shank_Dia.val,Hex_Head_Height.val) + + elif Head_Type['CAP'][0].val: + Head_Verts,Head_Faces,Head_Height = Create_Cap_Head(Bit_Dia,Cap_Head_Dia.val,Shank_Dia.val,Cap_Head_Height.val,Cap_Head_Dia.val*(1.0/19.0),Cap_Head_Dia.val*(1.0/19.0)) + + elif Head_Type['DOME'][0].val: + Head_Verts,Head_Faces,Head_Height = Create_Dome_Head(Bit_Dia,Dome_Head_Dia.val,Shank_Dia.val,Hex_Head_Height.val,1,1,0) + + elif Head_Type['PAN'][0].val: + Head_Verts,Head_Faces,Head_Height = Create_Pan_Head(Bit_Dia,Pan_Head_Dia.val,Shank_Dia.val,Hex_Head_Height.val,1,1,0) + + + Face_Start = len(verts) + verts.extend(Move_Verts_Up_Z(Bit_Verts,Head_Height)) + faces.extend(Copy_Faces(Bit_Faces,Face_Start)) + + Face_Start = len(verts) + verts.extend(Move_Verts_Up_Z(Head_Verts,Head_Height)) + faces.extend(Copy_Faces(Head_Faces,Face_Start)) + + Face_Start = len(verts) + Thread_Verts,Thread_Faces,Thread_Height = Create_External_Thread(Shank_Dia.val,Shank_Length.val,Minor_Dia.val,Major_Dia.val,Pitch.val,Thread_Length.val,Crest_Percent.val,Root_Percent.val) + + verts.extend(Move_Verts_Up_Z(Thread_Verts,00)) + faces.extend(Copy_Faces(Thread_Faces,Face_Start)) + + return Move_Verts_Up_Z(verts,Thread_Height),faces + + + + + + + +########################################################################################## +########################################################################################## +## Create Internal Thread +########################################################################################## +########################################################################################## + + +def Create_Internal_Thread_Start_Verts(verts,INNER_RADIUS,OUTTER_RADIUS,PITCH,DIV,CREST_PERCENT,ROOT_PERCENT,Height_Offset): + + + Ret_Row = 0; + + Height_Offset = Height_Offset + PITCH #Move the offset up so that the verts start at + #at the correct place (Height_Start) + + Half_Pitch = float(PITCH)/2 + Height_Start = Height_Offset - PITCH + Height_Step = float(PITCH)/float(DIV) + Deg_Step = 360.0 /float(DIV) + + Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100) + Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100) + Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0 + + + Rank = float(OUTTER_RADIUS - INNER_RADIUS)/float(DIV) + for j in range(1): + + for i in range(DIV+1): + z = Height_Offset - (Height_Step*i) + if z > Height_Start: + z = Height_Start + x = sin(radians(i*Deg_Step))*OUTTER_RADIUS + y = cos(radians(i*Deg_Step))*OUTTER_RADIUS + verts.append([x,y,z]) + Height_Offset -= Crest_Height + Ret_Row += 1 + + for i in range(DIV+1): + z = Height_Offset - (Height_Step*i) + if z > Height_Start: + z = Height_Start + + x = sin(radians(i*Deg_Step))*OUTTER_RADIUS + y = cos(radians(i*Deg_Step))*OUTTER_RADIUS + verts.append([x,y,z ]) + Height_Offset -= Crest_to_Root_Height + Ret_Row += 1 + + + for i in range(DIV+1): + z = Height_Offset - (Height_Step*i) + if z > Height_Start: + z = Height_Start + + x = sin(radians(i*Deg_Step))*INNER_RADIUS + y = cos(radians(i*Deg_Step))*INNER_RADIUS + if j == 0: + x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank)) + y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank)) + verts.append([x,y,z ]) + Height_Offset -= Root_Height + Ret_Row += 1 + + for i in range(DIV+1): + z = Height_Offset - (Height_Step*i) + if z > Height_Start: + z = Height_Start + + x = sin(radians(i*Deg_Step))*INNER_RADIUS + y = cos(radians(i*Deg_Step))*INNER_RADIUS + + if j == 0: + x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank)) + y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank)) + verts.append([x,y,z ]) + Height_Offset -= Root_to_Crest_Height + Ret_Row += 1 + + return Ret_Row,Height_Offset + + +def Create_Internal_Thread_End_Verts(verts,INNER_RADIUS,OUTTER_RADIUS,PITCH,DIV,CREST_PERCENT,ROOT_PERCENT,Height_Offset): + + + Ret_Row = 0; + + Half_Pitch = float(PITCH)/2 + #Height_End = Height_Offset - PITCH - PITCH - PITCH- PITCH - PITCH- PITCH + Height_End = Height_Offset - PITCH + #Height_End = -2.1 + Height_Step = float(PITCH)/float(DIV) + Deg_Step = 360.0 /float(DIV) + + Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100) + Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100) + Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0 + + + + Rank = float(OUTTER_RADIUS - INNER_RADIUS)/float(DIV) + + Num = 0 + + for j in range(2): + + for i in range(DIV+1): + z = Height_Offset - (Height_Step*i) + if z < Height_End: + z = Height_End + x = sin(radians(i*Deg_Step))*OUTTER_RADIUS + y = cos(radians(i*Deg_Step))*OUTTER_RADIUS + verts.append([x,y,z]) + Height_Offset -= Crest_Height + Ret_Row += 1 + + + for i in range(DIV+1): + z = Height_Offset - (Height_Step*i) + if z < Height_End: + z = Height_End + + x = sin(radians(i*Deg_Step))*OUTTER_RADIUS + y = cos(radians(i*Deg_Step))*OUTTER_RADIUS + verts.append([x,y,z ]) + Height_Offset -= Crest_to_Root_Height + Ret_Row += 1 + + + for i in range(DIV+1): + z = Height_Offset - (Height_Step*i) + if z < Height_End: + z = Height_End + + x = sin(radians(i*Deg_Step))*INNER_RADIUS + y = cos(radians(i*Deg_Step))*INNER_RADIUS + if j == Num: + x = sin(radians(i*Deg_Step))*(INNER_RADIUS + (i*Rank)) + y = cos(radians(i*Deg_Step))*(INNER_RADIUS + (i*Rank)) + if j > Num: + x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS) + y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS ) + + verts.append([x,y,z ]) + Height_Offset -= Root_Height + Ret_Row += 1 + + + for i in range(DIV+1): + z = Height_Offset - (Height_Step*i) + if z < Height_End: + z = Height_End + + x = sin(radians(i*Deg_Step))*INNER_RADIUS + y = cos(radians(i*Deg_Step))*INNER_RADIUS + + if j == Num: + x = sin(radians(i*Deg_Step))*(INNER_RADIUS + (i*Rank)) + y = cos(radians(i*Deg_Step))*(INNER_RADIUS + (i*Rank)) + if j > Num: + x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS ) + y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS ) + + verts.append([x,y,z ]) + Height_Offset -= Root_to_Crest_Height + Ret_Row += 1 + + + return Ret_Row,Height_End # send back Height End as this is the lowest point + + +def Create_Internal_Thread(INNER_DIA,OUTTER_DIA,PITCH,HEIGHT,CREST_PERCENT,ROOT_PERCENT,INTERNAL = 1): + verts = [] + faces = [] + + DIV = 36 + + INNER_RADIUS = INNER_DIA/2 + OUTTER_RADIUS = OUTTER_DIA/2 + + Half_Pitch = float(PITCH)/2 + Deg_Step = 360.0 /float(DIV) + Height_Step = float(PITCH)/float(DIV) + + Num = int(round((HEIGHT- PITCH)/PITCH)) # less one pitch for the start and end that is 1/2 pitch high + + Col = 0 + Row = 0 + + + Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100) + Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100) + Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0 + + Height_Offset = 0 + FaceStart = len(verts) + + Row_Inc,Height_Offset = Create_Internal_Thread_Start_Verts(verts,INNER_RADIUS,OUTTER_RADIUS,PITCH,DIV,CREST_PERCENT,ROOT_PERCENT,Height_Offset) + Row += Row_Inc + + for j in range(Num): + + for i in range(DIV+1): + x = sin(radians(i*Deg_Step))*OUTTER_RADIUS + y = cos(radians(i*Deg_Step))*OUTTER_RADIUS + verts.append([x,y,Height_Offset - (Height_Step*i) ]) + Height_Offset -= Crest_Height + Row += 1 + + for i in range(DIV+1): + x = sin(radians(i*Deg_Step))*OUTTER_RADIUS + y = cos(radians(i*Deg_Step))*OUTTER_RADIUS + verts.append([x,y,Height_Offset - (Height_Step*i) ]) + Height_Offset -= Crest_to_Root_Height + Row += 1 + + + for i in range(DIV+1): + x = sin(radians(i*Deg_Step))*INNER_RADIUS + y = cos(radians(i*Deg_Step))*INNER_RADIUS + verts.append([x,y,Height_Offset - (Height_Step*i) ]) + Height_Offset -= Root_Height + Row += 1 + + for i in range(DIV+1): + x = sin(radians(i*Deg_Step))*INNER_RADIUS + y = cos(radians(i*Deg_Step))*INNER_RADIUS + verts.append([x,y,Height_Offset - (Height_Step*i) ]) + Height_Offset -= Root_to_Crest_Height + Row += 1 + + + Row_Inc,Height_Offset = Create_Internal_Thread_End_Verts(verts,INNER_RADIUS,OUTTER_RADIUS,PITCH,DIV,CREST_PERCENT,ROOT_PERCENT,Height_Offset) + Row += Row_Inc + + faces.extend(Build_Face_List_Quads(FaceStart,DIV,Row -1,INTERNAL)) + + return verts,faces,0 - Height_Offset + + + +########################################################################################## +########################################################################################## +## Create External Thread +########################################################################################## +########################################################################################## + + + +def Thread_Start3(verts,INNER_RADIUS,OUTTER_RADIUS,PITCH,DIV,CREST_PERCENT,ROOT_PERCENT,Height_Offset): + + + Ret_Row = 0; + + Half_Pitch = float(PITCH)/2 + Height_Start = Height_Offset - PITCH + Height_Step = float(PITCH)/float(DIV) + Deg_Step = 360.0 /float(DIV) + + Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100) + Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100) + Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0 + +#theard start + + Rank = float(OUTTER_RADIUS - INNER_RADIUS)/float(DIV) + for j in range(4): + + for i in range(DIV+1): + z = Height_Offset - (Height_Step*i) + if z > Height_Start: + z = Height_Start + x = sin(radians(i*Deg_Step))*OUTTER_RADIUS + y = cos(radians(i*Deg_Step))*OUTTER_RADIUS + verts.append([x,y,z]) + Height_Offset -= Crest_Height + Ret_Row += 1 + + for i in range(DIV+1): + z = Height_Offset - (Height_Step*i) + if z > Height_Start: + z = Height_Start + + x = sin(radians(i*Deg_Step))*OUTTER_RADIUS + y = cos(radians(i*Deg_Step))*OUTTER_RADIUS + verts.append([x,y,z ]) + Height_Offset -= Crest_to_Root_Height + Ret_Row += 1 + + + for i in range(DIV+1): + z = Height_Offset - (Height_Step*i) + if z > Height_Start: + z = Height_Start + + x = sin(radians(i*Deg_Step))*INNER_RADIUS + y = cos(radians(i*Deg_Step))*INNER_RADIUS + if j == 0: + x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank)) + y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank)) + verts.append([x,y,z ]) + Height_Offset -= Root_Height + Ret_Row += 1 + + for i in range(DIV+1): + z = Height_Offset - (Height_Step*i) + if z > Height_Start: + z = Height_Start + + x = sin(radians(i*Deg_Step))*INNER_RADIUS + y = cos(radians(i*Deg_Step))*INNER_RADIUS + + if j == 0: + x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank)) + y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank)) + verts.append([x,y,z ]) + Height_Offset -= Root_to_Crest_Height + Ret_Row += 1 + + return Ret_Row,Height_Offset + + +def Create_Shank_Verts(START_DIA,OUTTER_DIA,LENGTH,Z_LOCATION = 0): + + verts = [] + DIV = 36 + + START_RADIUS = START_DIA/2 + OUTTER_RADIUS = OUTTER_DIA/2 + + Opp = abs(START_RADIUS - OUTTER_RADIUS) + Taper_Lentgh = Opp/tan(radians(31)); + + if Taper_Lentgh > LENGTH: + Taper_Lentgh = 0 + + Stright_Length = LENGTH - Taper_Lentgh + + Deg_Step = 360.0 /float(DIV) + + Row = 0 + + Lowest_Z_Vert = 0; + + Height_Offset = Z_LOCATION + + + #ring + for i in range(DIV+1): + x = sin(radians(i*Deg_Step))*START_RADIUS + y = cos(radians(i*Deg_Step))*START_RADIUS + z = Height_Offset - 0 + verts.append([x,y,z]) + Lowest_Z_Vert = min(Lowest_Z_Vert,z) + Height_Offset -= Stright_Length + Row += 1 + + for i in range(DIV+1): + x = sin(radians(i*Deg_Step))*START_RADIUS + y = cos(radians(i*Deg_Step))*START_RADIUS + z = Height_Offset - 0 + verts.append([x,y,z]) + Lowest_Z_Vert = min(Lowest_Z_Vert,z) + Height_Offset -= Taper_Lentgh + Row += 1 + + + return verts,Row,Height_Offset + + +def Create_Thread_Start_Verts(INNER_DIA,OUTTER_DIA,PITCH,CREST_PERCENT,ROOT_PERCENT,Z_LOCATION = 0): + + verts = [] + DIV = 36 + + INNER_RADIUS = INNER_DIA/2 + OUTTER_RADIUS = OUTTER_DIA/2 + + Half_Pitch = float(PITCH)/2 + Deg_Step = 360.0 /float(DIV) + Height_Step = float(PITCH)/float(DIV) + + Row = 0 + + Lowest_Z_Vert = 0; + + Height_Offset = Z_LOCATION + + Height_Start = Height_Offset + + Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100) + Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100) + Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0 + + Rank = float(OUTTER_RADIUS - INNER_RADIUS)/float(DIV) + + Height_Offset = Z_LOCATION + PITCH + Cut_off = Z_LOCATION + + + for j in range(1): + + for i in range(DIV+1): + x = sin(radians(i*Deg_Step))*OUTTER_RADIUS + y = cos(radians(i*Deg_Step))*OUTTER_RADIUS + z = Height_Offset - (Height_Step*i) + if z > Cut_off : z = Cut_off + verts.append([x,y,z]) + Lowest_Z_Vert = min(Lowest_Z_Vert,z) + Height_Offset -= Crest_Height + Row += 1 + + for i in range(DIV+1): + x = sin(radians(i*Deg_Step))*OUTTER_RADIUS + y = cos(radians(i*Deg_Step))*OUTTER_RADIUS + z = Height_Offset - (Height_Step*i) + if z > Cut_off : z = Cut_off + verts.append([x,y,z]) + Lowest_Z_Vert = min(Lowest_Z_Vert,z) + Height_Offset -= Crest_to_Root_Height + Row += 1 + + for i in range(DIV+1): + x = sin(radians(i*Deg_Step))*OUTTER_RADIUS + y = cos(radians(i*Deg_Step))*OUTTER_RADIUS + z = Height_Offset - (Height_Step*i) + if z > Cut_off : z = Cut_off + verts.append([x,y,z]) + Lowest_Z_Vert = min(Lowest_Z_Vert,z) + Height_Offset -= Root_Height + Row += 1 + + for i in range(DIV+1): + x = sin(radians(i*Deg_Step))*OUTTER_RADIUS + y = cos(radians(i*Deg_Step))*OUTTER_RADIUS + z = Height_Offset - (Height_Step*i) + if z > Cut_off : z = Cut_off + verts.append([x,y,z]) + Lowest_Z_Vert = min(Lowest_Z_Vert,z) + Height_Offset -= Root_to_Crest_Height + Row += 1 + + + for j in range(2): + for i in range(DIV+1): + z = Height_Offset - (Height_Step*i) + if z > Height_Start: + z = Height_Start + x = sin(radians(i*Deg_Step))*OUTTER_RADIUS + y = cos(radians(i*Deg_Step))*OUTTER_RADIUS + verts.append([x,y,z]) + Lowest_Z_Vert = min(Lowest_Z_Vert,z) + Height_Offset -= Crest_Height + Row += 1 + + for i in range(DIV+1): + z = Height_Offset - (Height_Step*i) + if z > Height_Start: + z = Height_Start + + x = sin(radians(i*Deg_Step))*OUTTER_RADIUS + y = cos(radians(i*Deg_Step))*OUTTER_RADIUS + verts.append([x,y,z ]) + Lowest_Z_Vert = min(Lowest_Z_Vert,z) + Height_Offset -= Crest_to_Root_Height + Row += 1 + + + for i in range(DIV+1): + z = Height_Offset - (Height_Step*i) + if z > Height_Start: + z = Height_Start + + x = sin(radians(i*Deg_Step))*INNER_RADIUS + y = cos(radians(i*Deg_Step))*INNER_RADIUS + if j == 0: + x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank)) + y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank)) + verts.append([x,y,z ]) + Lowest_Z_Vert = min(Lowest_Z_Vert,z) + Height_Offset -= Root_Height + Row += 1 + + for i in range(DIV+1): + z = Height_Offset - (Height_Step*i) + if z > Height_Start: + z = Height_Start + + x = sin(radians(i*Deg_Step))*INNER_RADIUS + y = cos(radians(i*Deg_Step))*INNER_RADIUS + + if j == 0: + x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank)) + y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank)) + verts.append([x,y,z ]) + Lowest_Z_Vert = min(Lowest_Z_Vert,z) + Height_Offset -= Root_to_Crest_Height + Row += 1 + + + return verts,Row,Height_Offset + + + +def Create_Thread_Verts(INNER_DIA,OUTTER_DIA,PITCH,HEIGHT,CREST_PERCENT,ROOT_PERCENT,Z_LOCATION = 0): + verts = [] + + DIV = 36 + + INNER_RADIUS = INNER_DIA/2 + OUTTER_RADIUS = OUTTER_DIA/2 + + Half_Pitch = float(PITCH)/2 + Deg_Step = 360.0 /float(DIV) + Height_Step = float(PITCH)/float(DIV) + + NUM_OF_START_THREADS = 4.0 + NUM_OF_END_THREADS = 3.0 + Num = int((HEIGHT- ((NUM_OF_START_THREADS*PITCH) + (NUM_OF_END_THREADS*PITCH) ))/PITCH) + Row = 0 + + + Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100) + Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100) + Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0 + + + Height_Offset = Z_LOCATION + + Lowest_Z_Vert = 0; + FaceStart = len(verts) + + + for j in range(Num): + + for i in range(DIV+1): + x = sin(radians(i*Deg_Step))*OUTTER_RADIUS + y = cos(radians(i*Deg_Step))*OUTTER_RADIUS + z = Height_Offset - (Height_Step*i) + verts.append([x,y,z]) + Lowest_Z_Vert = min(Lowest_Z_Vert,z) + Height_Offset -= Crest_Height + Row += 1 + + for i in range(DIV+1): + x = sin(radians(i*Deg_Step))*OUTTER_RADIUS + y = cos(radians(i*Deg_Step))*OUTTER_RADIUS + z = Height_Offset - (Height_Step*i) + verts.append([x,y,z]) + Lowest_Z_Vert = min(Lowest_Z_Vert,z) + Height_Offset -= Crest_to_Root_Height + Row += 1 + + + for i in range(DIV+1): + x = sin(radians(i*Deg_Step))*INNER_RADIUS + y = cos(radians(i*Deg_Step))*INNER_RADIUS + z = Height_Offset - (Height_Step*i) + verts.append([x,y,z]) + Lowest_Z_Vert = min(Lowest_Z_Vert,z) + Height_Offset -= Root_Height + Row += 1 + + for i in range(DIV+1): + x = sin(radians(i*Deg_Step))*INNER_RADIUS + y = cos(radians(i*Deg_Step))*INNER_RADIUS + z = Height_Offset - (Height_Step*i) + verts.append([x,y,z]) + Lowest_Z_Vert = min(Lowest_Z_Vert,z) + Height_Offset -= Root_to_Crest_Height + Row += 1 + + return verts,Row,Height_Offset + + + +def Create_Thread_End_Verts(INNER_DIA,OUTTER_DIA,PITCH,CREST_PERCENT,ROOT_PERCENT,Z_LOCATION = 0): + verts = [] + + DIV = 36 + + INNER_RADIUS = INNER_DIA/2 + OUTTER_RADIUS = OUTTER_DIA/2 + + Half_Pitch = float(PITCH)/2 + Deg_Step = 360.0 /float(DIV) + Height_Step = float(PITCH)/float(DIV) + + Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100) + Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100) + Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0 + + Col = 0 + Row = 0 + + Height_Offset = Z_LOCATION + + Tapper_Height_Start = Height_Offset - PITCH - PITCH + + Max_Height = Tapper_Height_Start - PITCH + + Lowest_Z_Vert = 0; + + FaceStart = len(verts) + for j in range(4): + + for i in range(DIV+1): + z = Height_Offset - (Height_Step*i) + z = max(z,Max_Height) + Tapper_Radius = OUTTER_RADIUS + if z < Tapper_Height_Start: + Tapper_Radius = OUTTER_RADIUS - (Tapper_Height_Start - z) + + x = sin(radians(i*Deg_Step))*(Tapper_Radius) + y = cos(radians(i*Deg_Step))*(Tapper_Radius) + verts.append([x,y,z]) + Lowest_Z_Vert = min(Lowest_Z_Vert,z) + Height_Offset -= Crest_Height + Row += 1 + + for i in range(DIV+1): + z = Height_Offset - (Height_Step*i) + z = max(z,Max_Height) + Tapper_Radius = OUTTER_RADIUS + if z < Tapper_Height_Start: + Tapper_Radius = OUTTER_RADIUS - (Tapper_Height_Start - z) + + x = sin(radians(i*Deg_Step))*(Tapper_Radius) + y = cos(radians(i*Deg_Step))*(Tapper_Radius) + verts.append([x,y,z]) + Lowest_Z_Vert = min(Lowest_Z_Vert,z) + Height_Offset -= Crest_to_Root_Height + Row += 1 + + + for i in range(DIV+1): + z = Height_Offset - (Height_Step*i) + z = max(z,Max_Height) + Tapper_Radius = OUTTER_RADIUS - (Tapper_Height_Start - z) + if Tapper_Radius > INNER_RADIUS: + Tapper_Radius = INNER_RADIUS + + x = sin(radians(i*Deg_Step))*(Tapper_Radius) + y = cos(radians(i*Deg_Step))*(Tapper_Radius) + verts.append([x,y,z]) + Lowest_Z_Vert = min(Lowest_Z_Vert,z) + Height_Offset -= Root_Height + Row += 1 + + for i in range(DIV+1): + z = Height_Offset - (Height_Step*i) + z = max(z,Max_Height) + Tapper_Radius = OUTTER_RADIUS - (Tapper_Height_Start - z) + if Tapper_Radius > INNER_RADIUS: + Tapper_Radius = INNER_RADIUS + + x = sin(radians(i*Deg_Step))*(Tapper_Radius) + y = cos(radians(i*Deg_Step))*(Tapper_Radius) + verts.append([x,y,z]) + Lowest_Z_Vert = min(Lowest_Z_Vert,z) + Height_Offset -= Root_to_Crest_Height + Row += 1 + + return verts,Row,Height_Offset,Lowest_Z_Vert + + + + +def Create_External_Thread(SHANK_DIA,SHANK_LENGTH,INNER_DIA,OUTTER_DIA,PITCH,LENGTH,CREST_PERCENT,ROOT_PERCENT): + + verts = [] + faces = [] + + DIV = 36 + + Total_Row = 0 + Thread_Len = 0; + + Face_Start = len(verts) + Offset = 0.0; + + + Shank_Verts,Shank_Row,Offset = Create_Shank_Verts(SHANK_DIA,OUTTER_DIA,SHANK_LENGTH,Offset) + Total_Row += Shank_Row + + Thread_Start_Verts,Thread_Start_Row,Offset = Create_Thread_Start_Verts(INNER_DIA,OUTTER_DIA,PITCH,CREST_PERCENT,ROOT_PERCENT,Offset) + Total_Row += Thread_Start_Row + + + Thread_Verts,Thread_Row,Offset = Create_Thread_Verts(INNER_DIA,OUTTER_DIA,PITCH,LENGTH,CREST_PERCENT,ROOT_PERCENT,Offset) + Total_Row += Thread_Row + + + Thread_End_Verts,Thread_End_Row,Offset,Lowest_Z_Vert = Create_Thread_End_Verts(INNER_DIA,OUTTER_DIA,PITCH,CREST_PERCENT,ROOT_PERCENT,Offset ) + Total_Row += Thread_End_Row + + + verts.extend(Shank_Verts) + verts.extend(Thread_Start_Verts) + verts.extend(Thread_Verts) + verts.extend(Thread_End_Verts) + + faces.extend(Build_Face_List_Quads(Face_Start,DIV,Total_Row -1,0)) + faces.extend(Fill_Ring_Face(len(verts)-DIV,DIV,1)) + + return verts,faces,0.0 - Lowest_Z_Vert + + +########################################################################################## +########################################################################################## +## Create Nut +########################################################################################## +########################################################################################## + + +def add_Hex_Nut(FLAT,HOLE_DIA,HEIGHT): + global Global_Head_Height + global Global_NutRad + + verts = [] + faces = [] + HOLE_RADIUS = HOLE_DIA * 0.5 + Half_Flat = FLAT/2 + Half_Height = HEIGHT/2 + TopBevelRadius = Half_Flat - 0.05 + + Global_NutRad = TopBevelRadius + + Row = 0; + Lowest_Z_Vert = 0.0; + + verts.append([0.0,0.0,0.0]) + + + FaceStart = len(verts) + #inner hole + + x = sin(radians(0))*HOLE_RADIUS + y = cos(radians(0))*HOLE_RADIUS + verts.append([x,y,0.0]) + + + x = sin(radians(60/6))*HOLE_RADIUS + y = cos(radians(60/6))*HOLE_RADIUS + verts.append([x,y,0.0]) + + + x = sin(radians(60/3))*HOLE_RADIUS + y = cos(radians(60/3))*HOLE_RADIUS + verts.append([x,y,0.0]) + + + x = sin(radians(60/2))*HOLE_RADIUS + y = cos(radians(60/2))*HOLE_RADIUS + verts.append([x,y,0.0]) + Row += 1 + + #bevel + + x = sin(radians(0))*TopBevelRadius + y = cos(radians(0))*TopBevelRadius + vec1 = Mathutils.Vector([x,y,0.0]) + verts.append([x,y,0.0]) + + + x = sin(radians(60/6))*TopBevelRadius + y = cos(radians(60/6))*TopBevelRadius + vec2 = Mathutils.Vector([x,y,0.0]) + verts.append([x,y,0.0]) + + + x = sin(radians(60/3))*TopBevelRadius + y = cos(radians(60/3))*TopBevelRadius + vec3 = Mathutils.Vector([x,y,0.0]) + verts.append([x,y,0.0]) + + + x = sin(radians(60/2))*TopBevelRadius + y = cos(radians(60/2))*TopBevelRadius + vec4 = Mathutils.Vector([x,y,0.0]) + verts.append([x,y,0.0]) + Row += 1 + + #Flats + + x = tan(radians(0))*Half_Flat + dvec = vec1 - Mathutils.Vector([x,Half_Flat,0.0]) + verts.append([x,Half_Flat,-dvec.length]) + Lowest_Z_Vert = min(Lowest_Z_Vert,-dvec.length) + + + x = tan(radians(60/6))*Half_Flat + dvec = vec2 - Mathutils.Vector([x,Half_Flat,0.0]) + verts.append([x,Half_Flat,-dvec.length]) + Lowest_Z_Vert = min(Lowest_Z_Vert,-dvec.length) + + + x = tan(radians(60/3))*Half_Flat + dvec = vec3 - Mathutils.Vector([x,Half_Flat,0.0]) + Lowest_Point = -dvec.length + verts.append([x,Half_Flat,-dvec.length]) + Lowest_Z_Vert = min(Lowest_Z_Vert,-dvec.length) + + x = tan(radians(60/2))*Half_Flat + dvec = vec4 - Mathutils.Vector([x,Half_Flat,0.0]) + Lowest_Point = -dvec.length + verts.append([x,Half_Flat,-dvec.length]) + Lowest_Z_Vert = min(Lowest_Z_Vert,-dvec.length) + Row += 1 + + #down Bits Tri + x = tan(radians(0))*Half_Flat + verts.append([x,Half_Flat,Lowest_Point]) + + + x = tan(radians(60/6))*Half_Flat + verts.append([x,Half_Flat,Lowest_Point]) + + x = tan(radians(60/3))*Half_Flat + verts.append([x,Half_Flat,Lowest_Point]) + + x = tan(radians(60/2))*Half_Flat + verts.append([x,Half_Flat,Lowest_Point]) + Lowest_Z_Vert = min(Lowest_Z_Vert,Lowest_Point) + Row += 1 + + #down Bits + + x = tan(radians(0))*Half_Flat + verts.append([x,Half_Flat,-Half_Height]) + + x = tan(radians(60/6))*Half_Flat + verts.append([x,Half_Flat,-Half_Height]) + + x = tan(radians(60/3))*Half_Flat + verts.append([x,Half_Flat,-Half_Height]) + + x = tan(radians(60/2))*Half_Flat + verts.append([x,Half_Flat,-Half_Height]) + Lowest_Z_Vert = min(Lowest_Z_Vert,-Half_Height) + Row += 1 + + + + + faces.extend(Build_Face_List_Quads(FaceStart,3,Row - 1)) + + + Global_Head_Height = HEIGHT + + Tvert,tface = Mirror_Verts_Faces(verts,faces,'z',Lowest_Z_Vert) + verts.extend(Tvert) + faces.extend(tface) + + + Tvert,tface = Mirror_Verts_Faces(verts,faces,'y') + verts.extend(Tvert) + faces.extend(tface) + + S_verts,S_faces = SpinDup(verts,faces,360,6,'z') + return S_verts,S_faces,TopBevelRadius + + +def add_Nylon_Head(OUTSIDE_RADIUS,Z_LOCATION = 0): + DIV = 36 + verts = [] + faces = [] + Row = 0 + + INNER_HOLE = OUTSIDE_RADIUS - (OUTSIDE_RADIUS * (1.25/4.75)) + EDGE_THICKNESS = (OUTSIDE_RADIUS * (0.4/4.75)) + RAD1 = (OUTSIDE_RADIUS * (0.5/4.75)) + OVER_ALL_HEIGTH = (OUTSIDE_RADIUS * (2.0/4.75)) + + + FaceStart = len(verts) + + Start_Height = 0 - 3 + Height_Offset = Z_LOCATION + Lowest_Z_Vert = 0 + + x = INNER_HOLE + z = (Height_Offset - OVER_ALL_HEIGTH) + EDGE_THICKNESS + verts.append([x,0.0,z]) + Lowest_Z_Vert = min(Lowest_Z_Vert,z) + Row += 1 + + x = INNER_HOLE + z = (Height_Offset - OVER_ALL_HEIGTH) + verts.append([x,0.0,z]) + Lowest_Z_Vert = min(Lowest_Z_Vert,z) + Row += 1 + + + for i in range(180,80,-10): + x = sin(radians(i))*RAD1 + z = cos(radians(i))*RAD1 + verts.append([(OUTSIDE_RADIUS-RAD1)+x,0.0,((Height_Offset - OVER_ALL_HEIGTH)+RAD1)+z]) + Lowest_Z_Vert = min(Lowest_Z_Vert,z) + Row += 1 + + + x = OUTSIDE_RADIUS - 0 + z = Height_Offset + verts.append([x,0.0,z]) + Lowest_Z_Vert = min(Lowest_Z_Vert,z) + Row += 1 + + sVerts,sFaces = SpinDup(verts,faces,360,DIV,'z') + sVerts.extend(verts) #add the start verts to the Spin verts to complete the loop + + faces.extend(Build_Face_List_Quads(FaceStart,Row-1,DIV)) + + return Move_Verts_Up_Z(sVerts,0),faces,Lowest_Z_Vert + + + +def add_Nylon_Part(OUTSIDE_RADIUS,Z_LOCATION = 0): + DIV = 36 + verts = [] + faces = [] + Row = 0 + + INNER_HOLE = OUTSIDE_RADIUS - (OUTSIDE_RADIUS * (1.5/4.75)) + EDGE_THICKNESS = (OUTSIDE_RADIUS * (0.4/4.75)) + RAD1 = (OUTSIDE_RADIUS * (0.5/4.75)) + OVER_ALL_HEIGTH = (OUTSIDE_RADIUS * (2.0/4.75)) + PART_THICKNESS = OVER_ALL_HEIGTH - EDGE_THICKNESS + PART_INNER_HOLE = (OUTSIDE_RADIUS * (2.5/4.75)) + + FaceStart = len(verts) + + Start_Height = 0 - 3 + Height_Offset = Z_LOCATION + Lowest_Z_Vert = 0 + + + x = INNER_HOLE + EDGE_THICKNESS + z = Height_Offset + verts.append([x,0.0,z]) + Lowest_Z_Vert = min(Lowest_Z_Vert,z) + Row += 1 + + x = PART_INNER_HOLE + z = Height_Offset + verts.append([x,0.0,z]) + Lowest_Z_Vert = min(Lowest_Z_Vert,z) + Row += 1 + + x = PART_INNER_HOLE + z = Height_Offset - PART_THICKNESS + verts.append([x,0.0,z]) + Lowest_Z_Vert = min(Lowest_Z_Vert,z) + Row += 1 + + x = INNER_HOLE + EDGE_THICKNESS + z = Height_Offset - PART_THICKNESS + verts.append([x,0.0,z]) + Lowest_Z_Vert = min(Lowest_Z_Vert,z) + Row += 1 + + + sVerts,sFaces = SpinDup(verts,faces,360,DIV,'z') + sVerts.extend(verts) #add the start verts to the Spin verts to complete the loop + + faces.extend(Build_Face_List_Quads(FaceStart,Row-1,DIV)) + + return sVerts,faces,0 - Lowest_Z_Vert + + + +def Nut_Mesh(): + + verts = [] + faces = [] + Head_Verts = [] + Head_Faces= [] + + Face_Start = len(verts) + Thread_Verts,Thread_Faces,New_Nut_Height = Create_Internal_Thread(Minor_Dia.val,Major_Dia.val,Pitch.val,Hex_Nut_Height.val,Crest_Percent.val,Root_Percent.val,1) + verts.extend(Thread_Verts) + faces.extend(Copy_Faces(Thread_Faces,Face_Start)) + + Face_Start = len(verts) + Head_Verts,Head_Faces,Lock_Nut_Rad = add_Hex_Nut(Hex_Nut_Flat_Distance.val,Major_Dia.val,New_Nut_Height) + verts.extend((Head_Verts)) + faces.extend(Copy_Faces(Head_Faces,Face_Start)) + + LowZ = 0 - New_Nut_Height + + if Nut_Type['LOCK'][0].val: + Face_Start = len(verts) + Nylon_Head_Verts,Nylon_Head_faces,LowZ = add_Nylon_Head(Lock_Nut_Rad,0-New_Nut_Height) + verts.extend((Nylon_Head_Verts)) + faces.extend(Copy_Faces(Nylon_Head_faces,Face_Start)) + + Face_Start = len(verts) + Nylon_Verts,Nylon_faces,Temp_LowZ = add_Nylon_Part(Lock_Nut_Rad,0-New_Nut_Height) + verts.extend((Nylon_Verts)) + faces.extend(Copy_Faces(Nylon_faces,Face_Start)) + + + return Move_Verts_Up_Z(verts,0 - LowZ),faces + + + +################################################################################################## + + +def Create_Nut(): + + verts = [] + faces = [] + + + if Error_Check() : + return + + + verts, faces = Nut_Mesh() + Add_Mesh_To_Scene('Nut', verts, faces) + + +################################################################################################## + + +def Create_Bolt(): + verts = [] + faces = [] + + + if Error_Check() : + return + + verts, faces = MakeBolt() + Add_Mesh_To_Scene('Bolt', verts, faces) + + + +def Remove_Doubles_From_Mesh(verts,faces): + Ret_verts = [] + Ret_faces = [] + + is_editmode = Window.EditMode() # Store edit mode state + if is_editmode: Window.EditMode(0) # Python must get a mesh in object mode. + + Temp_mesh = Mesh.New('MeshTemp') # create a new mesh + + Temp_mesh.verts.extend(verts) # add vertices to mesh + Temp_mesh.faces.extend(faces) # add faces to the mesh (also adds edges) + + scn = Scene.GetCurrent() # link object to current scene + Temp_Object = scn.objects.new(Temp_mesh, 'ObjectTemp') + + Temp_mesh.remDoubles(0.010) + Temp_mesh.transform(Mathutils.Matrix([Global_Scale,0,0,0], [0,Global_Scale,0,0], [0,0,Global_Scale,0], [0,0,0, Global_Scale])) + Ret_verts[:] = [v.co for v in Temp_mesh.verts] + Ret_faces[:] = [ [v.index for v in f] for f in Temp_mesh.faces] + + #delete temp mesh + scn.objects.unlink(Temp_Object) + scn.update(0) + + if is_editmode: Window.EditMode(1) + return Ret_verts,Ret_faces + + + +def Add_Mesh_To_Scene(name, verts, faces): + + scn = Scene.GetCurrent() + if scn.lib: return + ob_act = scn.objects.active + + is_editmode = Window.EditMode() + + cursor = Window.GetCursorPos() + quat = None + + if is_editmode or Blender.Get('add_view_align'): # Aligning seems odd for editmode, but blender does it, oh well + try: quat = Blender.Mathutils.Quaternion(Window.GetViewQuat()) + except: pass + + + # Exist editmode for non mesh types + if ob_act and ob_act.type != 'Mesh' and is_editmode: + EditMode(0) + + # We are in mesh editmode + if Window.EditMode(): + me = ob_act.getData(mesh=1) + + if me.multires: + error_txt = 'Error%t|Unable to complete action with multires enabled' + Blender.Draw.PupMenu(error_txt) + print error_txt + return + + #Don't want to remove doubles and scale the existing + # mesh so we need to get the verts and the faces from + # a mesh that has been scaled. + verts,faces = Remove_Doubles_From_Mesh(verts, faces) + + # Add to existing mesh + # must exit editmode to modify mesh + Window.EditMode(0) + + me.sel = False + + vert_offset = len(me.verts) + face_offset = len(me.faces) + + + # transform the verts + txmat = Blender.Mathutils.TranslationMatrix(Blender.Mathutils.Vector(cursor)) + if quat: + mat = quat.toMatrix() + mat.invert() + mat.resize4x4() + txmat = mat * txmat + + txmat = txmat * ob_act.matrixWorld.copy().invert() + + + me.verts.extend(verts) + # Transform the verts by the cursor and view rotation + me.transform(txmat, selected_only=True) + + if vert_offset: + me.faces.extend([[i+vert_offset for i in f] for f in faces]) + else: + # Mesh with no data, unlikely + me.faces.extend(faces) + else: + + # Object mode add new + me = Mesh.New(name) + me.verts.extend(verts) + me.faces.extend(faces) + + + me.sel = True + + # Object creation and location + scn.objects.selected = [] + ob_act = scn.objects.new(me, name) + + me.remDoubles(0.010) + me.transform(Mathutils.Matrix([Global_Scale,0,0,0], [0,Global_Scale,0,0], [0,0,Global_Scale,0], [0,0,0, Global_Scale])) + + scn.objects.active = ob_act + + if quat: + mat = quat.toMatrix() + mat.invert() + mat.resize4x4() + ob_act.setMatrix(mat) + + ob_act.loc = cursor + + me.calcNormals() + + if is_editmode or Blender.Get('add_editmode'): + Window.EditMode(1) + + Blender.Redraw(-1)#Redraw all + +################################################################################################## + + + +def Load_Preset(): + + global Preset_Menu + global Shank_Dia + global Shank_Length + global Thread_Length + global Major_Dia + global Minor_Dia + global Pitch + global Crest_Percent + global Root_Percent + global Allen_Bit_Flat_Distance + global Allen_Bit_Depth + global Head_Height + global Hex_Head_Flat_Distance + global Head_Dia + global Dome_Head_Dia + global Pan_Head_Dia + global Philips_Bit_Dia + global Phillips_Bit_Depth + global Cap_Head_Height + + global Hex_Nut_Height + global Hex_Nut_Flat_Distance + + + if Preset_Menu.val == 1 : #M3 + Shank_Dia.val = 3.0 + #Pitch.val = 0.5 #Coarse + Pitch.val = 0.35 #Fine + Crest_Percent.val = 10 + Root_Percent.val = 10 + Major_Dia.val = 3.0 + Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val) + Hex_Head_Flat_Distance.val = 5.5 + Hex_Head_Height.val = 2.0 + Cap_Head_Dia.val = 5.5 + Cap_Head_Height.val = 3.0 + Allen_Bit_Flat_Distance.val = 2.5 + Allen_Bit_Depth.val = 1.5 + Pan_Head_Dia.val = 5.6 + Dome_Head_Dia.val = 5.6 + Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6) + Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val) + Hex_Nut_Height.val = 2.4 + Hex_Nut_Flat_Distance.val = 5.5 + Thread_Length.val = 6 + Shank_Length.val = 0.0 + + + if Preset_Menu.val == 2 : #M4 + Shank_Dia.val = 4.0 + #Pitch.val = 0.7 #Coarse + Pitch.val = 0.5 #Fine + Crest_Percent.val = 10 + Root_Percent.val = 10 + Major_Dia.val = 4.0 + Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val) + Hex_Head_Flat_Distance.val = 7.0 + Hex_Head_Height.val = 2.8 + Cap_Head_Dia.val = 7.0 + Cap_Head_Height.val = 4.0 + Allen_Bit_Flat_Distance.val = 3.0 + Allen_Bit_Depth.val = 2.0 + Pan_Head_Dia.val = 8.0 + Dome_Head_Dia.val = 8.0 + Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6) + Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val) + Hex_Nut_Height.val = 3.2 + Hex_Nut_Flat_Distance.val = 7.0 + Thread_Length.val = 8 + Shank_Length.val = 0.0 + + + if Preset_Menu.val == 3 : #M5 + Shank_Dia.val = 5.0 + #Pitch.val = 0.8 #Coarse + Pitch.val = 0.5 #Fine + Crest_Percent.val = 10 + Root_Percent.val = 10 + Major_Dia.val = 5.0 + Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val) + Hex_Head_Flat_Distance.val = 8.0 + Hex_Head_Height.val = 3.5 + Cap_Head_Dia.val = 8.5 + Cap_Head_Height.val = 5.0 + Allen_Bit_Flat_Distance.val = 4.0 + Allen_Bit_Depth.val = 2.5 + Pan_Head_Dia.val = 9.5 + Dome_Head_Dia.val = 9.5 + Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6) + Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val) + Hex_Nut_Height.val = 4.0 + Hex_Nut_Flat_Distance.val = 8.0 + Thread_Length.val = 10 + Shank_Length.val = 0.0 + + + if Preset_Menu.val == 4 : #M6 + Shank_Dia.val = 6.0 + #Pitch.val = 1.0 #Coarse + Pitch.val = 0.75 #Fine + Crest_Percent.val = 10 + Root_Percent.val = 10 + Major_Dia.val = 6.0 + Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val) + Hex_Head_Flat_Distance.val = 10.0 + Hex_Head_Height.val = 4.0 + Cap_Head_Dia.val = 10.0 + Cap_Head_Height.val = 6.0 + Allen_Bit_Flat_Distance.val = 5.0 + Allen_Bit_Depth.val = 3.0 + Pan_Head_Dia.val = 12.0 + Dome_Head_Dia.val = 12.0 + Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6) + Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val) + Hex_Nut_Height.val = 5.0 + Hex_Nut_Flat_Distance.val = 10.0 + Thread_Length.val = 12 + Shank_Length.val = 0.0 + + + if Preset_Menu.val == 5 : #M8 + Shank_Dia.val = 8.0 + #Pitch.val = 1.25 #Coarse + Pitch.val = 1.00 #Fine + Crest_Percent.val = 10 + Root_Percent.val = 10 + Major_Dia.val = 8.0 + Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val) + Hex_Head_Flat_Distance.val = 13.0 + Hex_Head_Height.val = 5.3 + Cap_Head_Dia.val = 13.5 + Cap_Head_Height.val = 8.0 + Allen_Bit_Flat_Distance.val = 6.0 + Allen_Bit_Depth.val = 4.0 + Pan_Head_Dia.val = 16.0 + Dome_Head_Dia.val = 16.0 + Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6) + Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val) + Hex_Nut_Height.val = 6.5 + Hex_Nut_Flat_Distance.val = 13.0 + Thread_Length.val = 16 + Shank_Length.val = 0.0 + + if Preset_Menu.val == 6 : #M10 + Shank_Dia.val = 10.0 + #Pitch.val = 1.5 #Coarse + Pitch.val = 1.25 #Fine + Crest_Percent.val = 10 + Root_Percent.val = 10 + Major_Dia.val = 10.0 + Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val) + Hex_Head_Flat_Distance.val = 17.0 + Hex_Head_Height.val = 6.4 + Cap_Head_Dia.val = 16.0 + Cap_Head_Height.val = 10.0 + Allen_Bit_Flat_Distance.val = 8.0 + Allen_Bit_Depth.val = 5.0 + Pan_Head_Dia.val = 20.0 + Dome_Head_Dia.val = 20.0 + Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6) + Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val) + Hex_Nut_Height.val = 8.0 + Hex_Nut_Flat_Distance.val = 17.0 + Thread_Length.val = 20 + Shank_Length.val = 0.0 + + + if Preset_Menu.val == 7 : #M12 + #Pitch.val = 1.75 #Coarse + Pitch.val = 1.50 #Fine + Crest_Percent.val = 10 + Root_Percent.val = 10 + Major_Dia.val = 12.0 + Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val) + Hex_Head_Flat_Distance.val = 19.0 + Hex_Head_Height.val = 7.5 + Cap_Head_Dia.val = 18.5 + Cap_Head_Height.val = 12.0 + Allen_Bit_Flat_Distance.val = 10.0 + Allen_Bit_Depth.val = 6.0 + Pan_Head_Dia.val = 24.0 + Dome_Head_Dia.val = 24.0 + Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6) + Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val) + Hex_Nut_Height.val = 10.0 + Hex_Nut_Flat_Distance.val = 19.0 + Shank_Dia.val = 12.0 + Shank_Length.val = 33.0 + Thread_Length.val = 32.0 + +############################################################################################## + +def Test(): + verts = [] + faces = [] + + if Error_Check() : + return + + verts, faces = MakeBolt() + + Add_Mesh_To_Scene("TestBolt", verts,faces) + + Window.Redraw(-1) + + + + +def event(evt, val): # the function to handle input events + + if evt == Draw.ESCKEY: + Draw.Exit() # exit when user presses ESC + return + + +def button_event(evt): # the function to handle Draw Button events + + if evt == On_Exit_Click: + Draw.Exit() # exit when user presses ESC + return + + if evt == On_Test_Click: + Test() + Draw.Redraw(1) + + if evt == On_Preset_Click: + Load_Preset() + Draw.Redraw(1) + + if evt == On_Create_Click: + if Model_Type['BOLT'][0].val: + Create_Bolt() + if Model_Type['NUT'][0].val: + Create_Nut() + Draw.Redraw(1) + + elif (evt in [On_Hex_Click, On_Cap_Click,On_Dome_Click,On_Pan_Click]): + for k in Head_Type.iterkeys(): + if Head_Type[k][1]!=evt: + Head_Type[k][0].val=0 + else: + Head_Type[k][0].val=1 + Draw.Redraw(1) + + elif (evt in [On_Bit_None_Click,On_Bit_Allen_Click,On_Bit_Philips_Click]): + for k in Bit_Type.iterkeys(): + if Bit_Type[k][1]!=evt: + Bit_Type[k][0].val=0 + else: + Bit_Type[k][0].val=1 + Draw.Redraw(1) + + elif (evt in [On_Model_Bolt_Click,On_Model_Nut_Click]): + for k in Model_Type.iterkeys(): + if Model_Type[k][1]!=evt: + Model_Type[k][0].val=0 + else: + Model_Type[k][0].val=1 + Draw.Redraw(1) + + elif (evt in [On_Hex_Nut_Click,On_Lock_Nut_Click]): + for k in Nut_Type.iterkeys(): + if Nut_Type[k][1]!=evt: + Nut_Type[k][0].val=0 + else: + Nut_Type[k][0].val=1 + Draw.Redraw(1) + +##################################################################################### + + +def Draw_Border(X1,Y1,X2,Y2): # X1,Y1 = Top Left X2,Y2 = Bottom Right + INDENT = 3 + + BGL.glColor3f(1.0,1.0,1.0) + BGL.glBegin(BGL.GL_LINES) + BGL.glVertex2i(X1+INDENT,Y1-INDENT) #top line + BGL.glVertex2i(X2-INDENT,Y1-INDENT) + + BGL.glVertex2i(X1+INDENT,Y1-INDENT) #left line + BGL.glVertex2i(X1+INDENT,Y2+INDENT) + BGL.glEnd() + + BGL.glColor3f(0.5,0.5,0.5) + BGL.glBegin(BGL.GL_LINES) + BGL.glVertex2i(X2-INDENT,Y1-INDENT) #Right line + BGL.glVertex2i(X2-INDENT,Y2+INDENT) + + BGL.glVertex2i(X1+INDENT,Y2+INDENT) #bottom line + BGL.glVertex2i(X2-INDENT,Y2+INDENT) + BGL.glEnd() + + + + +def Create_Tab(X1,Y1,X2,Y2,Title,Buttons): # X1,Y1 = Top Left X2,Y2 = Bottom Right + + BIT_BUTTON_WIDTH = 55 + BIT_BUTTON_HEIGHT = 18 + TITLE_HEIGHT = 15 + INDENT = 6 + BUTTON_GAP = 4 + + BGL.glColor3f(0.75, 0.75, 0.75) + BGL.glRecti(X1,Y1,X2,Y2) + + Draw_Border(X1,Y1,X2,Y2); + + BGL.glColor3f(0.0,0.0,0.0) + BGL.glRasterPos2d(X1+INDENT,Y1 - TITLE_HEIGHT) + Draw.Text(Title) + + Button_X = X1 + INDENT + Button_Y = Y1 - TITLE_HEIGHT - BIT_BUTTON_HEIGHT - 8 + + #Nut_Number_X = Nut_Button_X + #Nut_Number_Y = Nut_Button_Y - 25 + if (Buttons != 0): + key= Buttons.keys() + for k in key: + Buttons[k][0]= Draw.Toggle(k,Buttons[k][1],Button_X,Button_Y, BIT_BUTTON_WIDTH,BIT_BUTTON_HEIGHT,Buttons[k][0].val,Buttons[k][2]) + Button_X += BIT_BUTTON_WIDTH + BUTTON_GAP + + + +def Dispaly_Title_Bar(Y_POS,CONTROL_HEIGHT): + CONTROL_WIDTH = 250 + Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS -CONTROL_HEIGHT,"Bolt Factory V2.00",Model_Type) + + + +def Dispaly_Preset_Tab(Y_POS,CONTROL_HEIGHT): + CONTROL_WIDTH = 250 + BUTTON_Y_OFFSET = 40 + + Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS-CONTROL_HEIGHT,"Preset",0) + + name = "M3%x1|M4%x2|M5%x3|M6%x4|M8%x5|M10%x6|M12%x7" + + global Preset_Menu + Preset_Menu = Draw.Menu(name,No_Event,9,Y_POS-BUTTON_Y_OFFSET,50,18, Preset_Menu.val, "Predefined metric screw sizes.") + Draw.Button("Apply",On_Preset_Click,150,Y_POS-BUTTON_Y_OFFSET,55,18,"Apply the preset screw sizes.") + + +def Dispaly_Bit_Tab(Y_POS,CONTROL_HEIGHT): + + CONTROL_WIDTH = 250 + NUMBER_HEIGHT = 18 + NUMBER_WIDTH = CONTROL_WIDTH -3-3-3-3-3 + + Bit_Number_X = 3+3+3 + Bit_Number_Y = Y_POS - 64 + + Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS-CONTROL_HEIGHT,"Bit Type",Bit_Type) + + if Bit_Type['NONE'][0].val: + DoNothing = 1; + + elif Bit_Type['ALLEN'][0].val: + global Allen_Bit_Depth + Allen_Bit_Depth = Draw.Number('Bit Depth: ',No_Event,Bit_Number_X,Bit_Number_Y,NUMBER_WIDTH, NUMBER_HEIGHT,Allen_Bit_Depth.val, 0,100, '') + Bit_Number_Y -= NUMBER_HEIGHT + global Allen_Bit_Flat_Distance + Allen_Bit_Flat_Distance = Draw.Number('Flat Dist: ',No_Event,Bit_Number_X,Bit_Number_Y,NUMBER_WIDTH,NUMBER_HEIGHT,Allen_Bit_Flat_Distance.val, 0,100, '') + Bit_Number_Y -= NUMBER_HEIGHT + + elif Bit_Type['PHILLIPS'][0].val: + global Phillips_Bit_Depth + Phillips_Bit_Depth = Draw.Number('Bit Depth: ',No_Event,Bit_Number_X,Bit_Number_Y,NUMBER_WIDTH, NUMBER_HEIGHT,Phillips_Bit_Depth.val, 0,100, '') + Bit_Number_Y -= NUMBER_HEIGHT + global Philips_Bit_Dia + Philips_Bit_Dia = Draw.Number('Bit Dia: ',No_Event,Bit_Number_X,Bit_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Philips_Bit_Dia.val, 0,100, '') + Bit_Number_Y -= NUMBER_HEIGHT + + + +def Dispaly_Shank_Tab(Y_POS,CONTROL_HEIGHT): + + CONTROL_WIDTH = 250 + NUMBER_HEIGHT = 18 + NUMBER_WIDTH = CONTROL_WIDTH -3-3-3-3-3 + + Number_X = 3+3+3 + Number_Y_Pos = Y_POS - 40 + + Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS-CONTROL_HEIGHT,"Shank",0) + + global Shank_Length + Shank_Length = Draw.Number('Shank Length: ',No_Event,Number_X,Number_Y_Pos,NUMBER_WIDTH,NUMBER_HEIGHT, Shank_Length.val, 0,MAX_INPUT_NUMBER, 'some text tip') + Number_Y_Pos -= NUMBER_HEIGHT + + global Shank_Dia + Shank_Dia = Draw.Number('Shank Dia: ',No_Event,Number_X,Number_Y_Pos,NUMBER_WIDTH,NUMBER_HEIGHT, Shank_Dia.val, 0,MAX_INPUT_NUMBER, 'some text tip') + Number_Y_Pos -= NUMBER_HEIGHT + + + +def Dispaly_Thread_Tab(Y_POS,CONTROL_HEIGHT): + + CONTROL_WIDTH = 250 + NUMBER_HEIGHT = 18 + NUMBER_WIDTH = CONTROL_WIDTH -3-3-3-3-3 + + + Number_X = 3+3+3 + Number_Y_Pos = Y_POS - 40 + + Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS-CONTROL_HEIGHT,"Thread",0) + + global Thread_Length + if Model_Type['BOLT'][0].val: + Thread_Length = Draw.Number('Thread Length: ',No_Event, Number_X,Number_Y_Pos,NUMBER_WIDTH,NUMBER_HEIGHT, Thread_Length.val, 0,MAX_INPUT_NUMBER, '') + Number_Y_Pos -= NUMBER_HEIGHT + + global Major_Dia + Major_Dia = Draw.Number('Major Dia: ',No_Event,Number_X,Number_Y_Pos, NUMBER_WIDTH,NUMBER_HEIGHT, Major_Dia.val, 0,MAX_INPUT_NUMBER, '') + Number_Y_Pos -= NUMBER_HEIGHT + + global Minor_Dia + Minor_Dia = Draw.Number('Minor Dia: ',No_Event,Number_X,Number_Y_Pos, NUMBER_WIDTH,NUMBER_HEIGHT, Minor_Dia.val, 0,MAX_INPUT_NUMBER, '') + Number_Y_Pos -= NUMBER_HEIGHT + + global Pitch + Pitch = Draw.Number('Pitch: ',No_Event,Number_X,Number_Y_Pos,NUMBER_WIDTH,NUMBER_HEIGHT, Pitch.val, 0.1,7.0, '') + Number_Y_Pos -= NUMBER_HEIGHT + + global Crest_Percent + Crest_Percent = Draw.Number('Crest %: ',No_Event,Number_X,Number_Y_Pos,NUMBER_WIDTH,NUMBER_HEIGHT,Crest_Percent.val, 1,90, '') + Number_Y_Pos -= NUMBER_HEIGHT + + global Root_Percent + Root_Percent = Draw.Number('Root %: ',No_Event,Number_X,Number_Y_Pos,NUMBER_WIDTH,NUMBER_HEIGHT,Root_Percent.val, 1,90, '') + Number_Y_Pos -= NUMBER_HEIGHT + + + + +def Dispaly_Head_Tab(Y_POS,CONTROL_HEIGHT): + + CONTROL_WIDTH = 250 + NUMBER_HEIGHT = 18 + NUMBER_WIDTH = CONTROL_WIDTH -3-3-3-3-3 + + Head_Number_X = 3+3+3 + Head_Number_Y = Y_POS - 64 + + Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS-CONTROL_HEIGHT,"Head Type",Head_Type) + + if Head_Type['HEX'][0].val: + global Hex_Head_Height + Hex_Head_Height = Draw.Number('Head Height: ',No_Event,Head_Number_X ,Head_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Hex_Head_Height.val, 0,100, '') + Head_Number_Y -= NUMBER_HEIGHT + global Hex_Head_Flat_Distance + Hex_Head_Flat_Distance = Draw.Number('Head Hex Flat Distance ',No_Event,Head_Number_X,Head_Number_Y,NUMBER_WIDTH, NUMBER_HEIGHT,Hex_Head_Flat_Distance.val, 0,MAX_INPUT_NUMBER, '') + Head_Number_Y -= NUMBER_HEIGHT + + elif Head_Type['CAP'][0].val: + global Cap_Head_Height + Cap_Head_Height = Draw.Number('Head Height: ',No_Event, Head_Number_X,Head_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Cap_Head_Height.val, 0,100, '') + Head_Number_Y -= NUMBER_HEIGHT + global Cap_Head_Dia + Cap_Head_Dia = Draw.Number('Head Dia ',No_Event,Head_Number_X,Head_Number_Y,NUMBER_WIDTH, NUMBER_HEIGHT,Cap_Head_Dia.val, 0,MAX_INPUT_NUMBER, '') + Head_Number_Y -= NUMBER_HEIGHT + + elif Head_Type['DOME'][0].val: + global Dome_Head_Dia + Dome_Head_Dia = Draw.Number(' Dome Head Dia ',No_Event,Head_Number_X,Head_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Dome_Head_Dia.val, 0,MAX_INPUT_NUMBER, '') + Head_Number_Y -= NUMBER_HEIGHT + + elif Head_Type['PAN'][0].val: + global Pan_Head_Dia + Pan_Head_Dia = Draw.Number('Pan Head Dia ',No_Event,Head_Number_X,Head_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Pan_Head_Dia.val, 0,MAX_INPUT_NUMBER, '') + Head_Number_Y -= NUMBER_HEIGHT + + + + +def Dispaly_Nut_Tab(Y_POS,CONTROL_HEIGHT): + + CONTROL_WIDTH = 250 + NUMBER_HEIGHT = 18 + NUMBER_WIDTH = CONTROL_WIDTH -3-3-3-3-3 + + Nut_Number_X = 3+3+3 + Nut_Number_Y = Y_POS - 64 + + Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS-CONTROL_HEIGHT,"Nut Type",Nut_Type) + + #if Nut_Type['HEX'][0].val: + global Hex_Nut_Height + Hex_Nut_Height = Draw.Number('Nut Height: ',No_Event,Nut_Number_X ,Nut_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Hex_Nut_Height.val, 0,MAX_INPUT_NUMBER, '') + Nut_Number_Y -= NUMBER_HEIGHT + global Hex_Nut_Flat_Distance + Hex_Nut_Flat_Distance = Draw.Number('Nut Flat Distance ',No_Event,Nut_Number_X,Nut_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Hex_Nut_Flat_Distance.val, 0,MAX_INPUT_NUMBER, '') + Nut_Number_Y -= NUMBER_HEIGHT + + +def Dispaly_Bolt_Tab(): + + Dispaly_Shank_Tab(284,66) + Dispaly_Head_Tab(374,90) + Dispaly_Bit_Tab(464,90) + + +########################################################################################## + +def gui(): # the function to draw the screen + + CONTROL_WIDTH = 250 + + BGL.glClearColor(0.6, 0.6, 0.6, 1.0) + BGL.glClear(BGL.GL_COLOR_BUFFER_BIT) + + BGL.glColor3f(0.75, 0.75, 0.75) + BGL.glRecti(3,30,CONTROL_WIDTH,3) + + Dispaly_Title_Bar(514,50); + + if Model_Type['BOLT'][0].val: + Dispaly_Bolt_Tab(); + + if Model_Type['NUT'][0].val: + Dispaly_Nut_Tab(464,246); + + Dispaly_Thread_Tab(218,138) + + Dispaly_Preset_Tab(80,50) + + Draw.PushButton("Create",On_Create_Click,6,8,55,18,"Create Bolt") + Draw.Button("Exit",On_Exit_Click,6+55+4,8,55,18) + +# Draw.Button("Test",On_Test_Click,150,10,55,20) + +Load_Preset() +Draw.Register(gui, event, button_event) # registering the 3 callbacks diff --git a/release/scripts/wizard_landscape_ant.py b/release/scripts/wizard_landscape_ant.py new file mode 100644 index 00000000000..405c06432ca --- /dev/null +++ b/release/scripts/wizard_landscape_ant.py @@ -0,0 +1,2148 @@ +#!BPY +""" +Name: 'Landscape Generator (A.N.T)' +Blender: 248 +Group: 'Wizards' +Tip: 'Create landscape mesh.' +""" + +__author__ = "Jimmy Hazevoet" +__url__ = ('http://wiki.blender.org/index.php/Scripts/Manual/Wizards/ANTLandscape','elysiun') +__version__ = "v.1.05 03-2007" +__bpydoc__ = """\ + +Another Noise Tool 'Landscape' v.1.05 + +This script uses noise functions to create a terrain from a grid mesh. + +Usage: + +Make new terrain: press the "Add New Grid" button, change some noise settings and press the "Update" button. + +Work on previous made grid: select the grid/terrain in the 3D view, and press the "Assign" button. + +Tip: use a low resolution grid mesh and add some Multires levels for detail + +Note: when using Multires materials can get weird, +only apply materials when your terrain is ready, or not use Multires. + +This Script creates a landscape mesh. +Press the Auto button when you start the script. +Then the Generate Button & read it's tooltip. +The mesh created is average 16000 verts. +To me the mesh appears quite small in the 3d view. +Just Press S in the 3d view to scale it up. +This saves overhead drawing the Mesh. + +Known Issues: +If the mesh is not drawn in the 3d view first time, +Move your mouse to the 3d view, or press the button again. + +Not really an issue, more to be aware. +Due to the complex nature & design of the script, it only creates one mesh at a time. +When you press Generate or Reset, +Even if you have Closed then Opened the script or .blend file, +The mesh Will be Overwritten. +To create Multiple Landscapes you Must Re-Name or save the Mesh +in Blender's F7 menu Links & Materials Panel. + +Readme: +v.1.04: +_ New G.U.I. +_ New noise types like: +Double_Terrain, +StatsByAlt_Terrain, +slickRock, +ditorted_heteroTerrain, +vlNoise_turbulence, +and many more. + +New fractalized Effect functions. +Effect types such as: gradient, +waves and bumps, dome, piramide, +squares, grid, shattered rocks, +lunar, and many more. + +Bias types: Sin, Cos, Tri, Saw, +and Default(no bias). + +For example the 'Rings' effect +with 'Sin Bias' makes 'Rings' +and 'Default Bias' makes 'Dome'. +The Effect 'Mix factor' Slider gives control over how much of the Effect is vissible, +-1.0=noise, 0.0=average, 1.0=effect +this slider controls also the 'Warp amount' if mix type 'Warp' is selected. + +Image effect: mix image with noise +_ IPOCurve Filter: use Ipo curve to filter terrain height. +I know it's a bit strange to use animation curves for landscape modelling, (actualy i want a curves panel in my G.U.I. but i dont know how to do that) +the downside of this method is that you have this 'Empty' moving around in your scene, so put it on another layer and 'Pin' the Ipo block so that it stays visible. +Usage: +Add one 'Empty' Object to your scene, now add one Loc Key at Frame 1, go to Frame 101 (UpArrow ten times), +move the 'Empty' +100 units in X+ direction and add another Loc Key, open the Ipo Curve Editor Window, rename this IpoBlock if you want, +Copie the first curve to buffer and Paste it in the empty slots (from top to bottom), now you can edit the curves freely. +(use the 'Pin' option to keep the curves visible while other objects are selected) +Set the CurveLength and CurveHeight Button value's according to the length and height of the selected curve. +A curve filter is very versatile when it comes to 'height' filtering. + +_ PreView in UV/Image Editor Window: +The preview image is now rendered as Blender.Image and will be saved to file directory as 'ANTview_size.tga' +you have to select 'ANTview_size.tga' in the UV/Image Editor Window +now it's posible to render and save a large HeightMap image (you can also create nice texture images when the VertCol gradient is enabled), +! If you Change the preview image Size a New Blender.Image object is created. (one for size 256, one for size 512 one for.....) ! + +_ VertexColours: use any image as colour gradient. +This function actualy uses one 'row' of pixels from a image to produce the color gradient, +Make one or more custom gradient images with the Gimp or any other graphics software, the gradients must go from left to right (left is bottom and right is top. +you only need one row of pixels so you can put 10 gradients in a 256*10 image.(higher resolutions like 512*n or 1024*n gives smoother result) +Set Window DrawMode 'Textured' , and set the 'VCol Paint' option in the Materials panel ! + +_ Mesh Tiles: Create large scale terrains. + +_ Vertices Selection: select flat areas. + +_ Keyboard HotKeys: +SPACE = Update mesh. +R = Randomise. +V = Redraw preview. + +_ and more... + +""" + + + + +### +# +# Alt+P to start script. +# +### +# scroll down to see info about updates +## +################################################################################################################ +# Another Noise Tool 'Landscape' +# Jimmy Hazevoet +# license: Do whatever you want with it. +################################################################################################################ + +################################################################################################################ +# v.1.04: +# +# _ New G.U.I. +# _ New noise types like: Double_Terrain, StatsByAlt_Terrain, slickRock, ditorted_heteroTerrain, vlNoise_turbulence, and many more. +# _ New fractalized Effect functions. +# Effect types such as: gradient, waves and bumps, dome, piramide, squares, grid, shattered rocks, lunar, and many more. +# Bias types: Sin, Cos, Tri, Saw, and Default(no bias). +# For example the 'Rings' effect with 'Sin Bias' makes 'Rings' and 'Default Bias' makes 'Dome'. +# _ The Effect 'Mix factor' Slider gives control over how much of the Effect is vissible, -1.0=noise, 0.0=average, 1.0=effect +# this slider controls also the 'Warp amount' if mix type 'Warp' is selected. +# _ Image effect: mix image with noise +# _ IPOCurve Filter: use Ipo curve to filter terrain height. +# I know it's a bit strange to use animation curves for landscape modelling, (actualy i want a curves panel in my G.U.I. but i dont know how to do that) +# the downside of this method is that you have this 'Empty' moving around in your scene, so put it on another layer and 'Pin' the Ipo block so that it stays visible. +# Usage: +# Add one 'Empty' Object to your scene, now add one Loc Key at Frame 1, go to Frame 101 (UpArrow ten times), +# move the 'Empty' +100 units in X+ direction and add another Loc Key, open the Ipo Curve Editor Window, rename this IpoBlock if you want, +# Copie the first curve to buffer and Paste it in the empty slots (from top to bottom), now you can edit the curves freely. +# (use the 'Pin' option to keep the curves visible while other objects are selected) +# Set the CurveLength and CurveHeight Button value's according to the length and height of the selected curve. +# A curve filter is very versatile when it comes to 'height' filtering. +# _ PreView in UV/Image Editor Window: +# The preview image is now rendered as Blender.Image and will be saved to file directory as 'ANTview_size.tga' +# you have to select 'ANTview_size.tga' in the UV/Image Editor Window +# now it's posible to render and save a large HeightMap image (you can also create nice texture images when the VertCol gradient is enabled), +# ! If you Change the preview image Size a New Blender.Image object is created. (one for size 256, one for size 512 one for.....) ! +# _ VertexColours: use any image as colour gradient. +# This function actualy uses one 'row' of pixels from a image to produce the color gradient, +# Make one or more custom gradient images with the Gimp or any other graphics software, the gradients must go from left to right (left is bottom and right is top. +# you only need one row of pixels so you can put 10 gradients in a 256*10 image.(higher resolutions like 512*n or 1024*n gives smoother result) +# Set Window DrawMode 'Textured' , and set the 'VCol Paint' option in the Materials panel ! +# _ Mesh Tiles: Create large scale terrains. +# _ Vertices Selection: select flat areas. +# _ Keyboard HotKeys: +# SPACE = Update mesh. +# R = Randomise. +# V = Redraw preview. +# _ and more... +################################################################################################################ + +################################################################################################################ +# BugFix: Sept./2006 v.1.04a +#----------------------------- +# _Image Effect did not worked well with tiled mesh. Fixed (now use Freq. and Loc. buttons to scale and position image). +# +################################################################################################################ + + +################################################################################################################ +# UPDATE: v.1.05 03-2007 +#--------------------------------------------------------------------------------------------------------------- +# +# _ New: Save and Load function, save your settings to a .ant file. +# __NOTE: when saving/loading settings to/from a file, +# make sure the filename/path is not too long! +# __HOTKEY__ Load from file: L +# __HOTKEY__ Save to file : S +# +# _ New mesh code, uses Mesh instead of NMesh, +# this gives a small speed improvement and alows you to use Multires. +# +# Usage: Select a Grid/Terrain mesh and hit the Assign button, now you can work on it, when ready you assign another. +# +# _ New: 'Musgrave' noise types, 'Random noise' and 'Constant' in 'Effects' section. +# _ New: 'Custom Effect', write custom formulae ( x,y, a,b, from math import *, from Blender.Noise import * ) +# _ New: 'Custom Height Filter', write custom formulae ( x,y, h, a,b, from math import *, from Blender.Noise import * ) +# _ New: 'Change Filter Order', Toggle: OFF = Noise+Effect+Falloff+FILTER / ON = Noise+FILTER+Effect+Falloff +# +# _ If you want to make a tiled terrain, you need to set the coordinates to "WorldSpace" or "Center at Cursor" (in G.U.I.Noise panel), +# create and place the grid meshes. now one by one select, assign and update, you may need to adjust the "EdgeFalloff" size. +# +# WARNING!: when using Multires, materials can get weird (?), so apply materials when your terrain is finnished. +# +############################################################################################################### + + +############################################################################################################### +# +## Execute Script: Alt P +# + + +import Blender +from Blender import * +from math import * +from Blender.Noise import * +from Blender.Draw import * +from Blender.BGL import * +from Blender import Image +import string +from string import strip +import BPyMathutils +from BPyMathutils import genrand +from random import choice +scene = Scene.GetCurrent() + +###--------------------------------------------------------------------------- + +CurVersion = 'A.N.T.Landscape v.1.05' + +##--------------------------------------------------------------------------- +# Customise default settings: ---------------------------------------------- + +# Names: +antfilename = 'Terrain' # Default filename +previewname = Create('') # Default preview Image name +DefaultIpoName = '' # Default Ipo DataBlock name (for height filter) +# G.U.I.: +FullScreen = Create( 0 ) # FullScreen on/off +# gui colors: +ledcolors = [ [1.0,0.498,0.498], [1.0,0.698,0.498], [1.0,0.898,0.498], [0.898,1.0,0.498], [0.698,1.0,0.498], [0.498,1.0,0.498], [0.498,1.0,0.698], [0.498,1.0,0.898], [0.600,0.918,1.0], [0.6,0.757,1.0], [0.6,0.6,1.0], [0.757,0.6,1.0], [0.898,0.498,1.0], [1.0,0.498,0.898] ] +#ledcolor = [ 1.0, 0.5, 0.0 ] +lightgrey = [ 0.76, 0.76, 0.76 ] # gui col. +grey = [ 0.6, 0.6, 0.6 ] # panel col. +background = [ 0.7, 0.7, 0.7, 1.0 ] # background col. +black = [ 0.0, 0.0, 0.0 ] # text col. +white = [ 1.0, 1.0, 1.0 ] +# gui size +size_x = 320 # gui x size +size_y = 280 # gui y size +# tabs +guitabs = [ Create( 1 ), Create( 0 ), Create( 0 ), Create( 0 ), Create( 0 ) ] # gui Tabs +# How long does it take to generate a mesh or image ? +print_time = 0 # 1 = Print time in console. + +# end customise. ---------------------------------------------------------- +##-------------------------------------------------------------------------- +###-------------------------------------------------------------------------- +####-------------------------------------------------------------------------- +##--------------------------------------------------------------------------- + +dirpath=Blender.sys.dirname(Blender.Get('filename')) +fname=dirpath.replace('\\','/')+'/' + antfilename + '.ant' +txtFile = Create( fname ) + +###--------------------------------------------------------------------------- +columns = 10 # gui columns +rows = 13 # gui rows +actob = [] # active object +actme = [] # active mesh +ipoblockname='' +thiscurve=[] +selectedcurve=0 +phi=3.14159265359 +# events +App_Evt = 144 +New_Evt = 166 +SelFile_Evt = 71 +LoadFile_Evt = 72 +SaveFile_Evt = 73 +UseMe_Evt = 74 +No_Evt = 1 +Btn_Evt = 2 +Msh_Evt = 12 +Upd_Evt = 3 +Rndm_Evt = 4 +Load_Evt = 5 +Sel_Evt = 6 +Save_Evt = 7 +Rend_Evt = 8 +End_Evt = 9 +Scrn_Evt = 15 +Im_Evt = 16 +gt0_Evt = 20 +gt1_Evt = 21 +gt2_Evt = 22 +gt3_Evt = 23 +gt4_Evt = 24 +Ipo_Evt = 17 +New_Ipo_Evt=700 + +###--------------------------------------------------------------------------- +# menus +noisetypemenu = "Noise type: %t|multiFractal %x0|ridgedMFractal %x1|hybridMFractal %x2|heteroTerrain %x3|fBm %x4|turbulence %x5|Voronoi turb. %x6|vlNoise turb. %x7|noise %x8|cellNoise %x9|Marble %x10|lava_multiFractal %x11|slopey_noise %x12|duo_multiFractal %x13|distorted_heteroTerrain %x14|slickRock %x15|terra_turbulence %x16|rocky_fBm %x17|StatsByAlt_Terrain %x18|Double_Terrain %x19|Shattered_hTerrain %x20|vlhTerrain %x21" +noisebasismenu = "Basis %t|Blender Original%x0|Original Perlin%x1|Improved Perlin%x2|Voronoi_F1%x3|Voronoi_F2%x4|Voronoi_F3%x5|Voronoi_F4%x6|Voronoi_F2-F1%x7|Voronoi Crackle%x8|CellNoise%x9" +voronitypemenu = "Voronoi type %t|Distance %x0|Distance Squared %x1|Manhattan %x2|Chebychev %x3|Minkovsky 1/2 %x4|Minkovsky 4 %x5|Minkovsky %x6" +tBasismodemenu = "Terrain basis mode: %t|noise %x0|ridged noise %x1|vlNoise %x2|ridged vlNoise %x3" +effecttypemenu = ['Effect Type %t','No Effect %x0','Image %x1','Turbulence %x2','vlNoise %x3','Marble %x4', 'multiFractal %x5','ridgedMFractal %x6','hybridMFractal %x7','heteroTerrain %x8','fBm %x9', 'Gradient %x10','Waves and Bumps %x11','ZigZag %x12','Wavy %x13','Sine Bump %x14','Dots %x15','Rings / Dome %x16','Spiral %x17','Square / Piramide %x18','Blocks %x19','Grid %x20','Tech %x21','Crackle %x22','Sparse Cracks %x23','Shattered Rocks %x24','Lunar %x25','Cosine noise %x26','Spike noise %x27','Stone noise %x28','Flat Turb %x29','Flat Voroni %x30','Random noise %x31','Constant %x32','Custom Effect %x33' ] +mixtypemenu = ['Mix Type %t','Effect only %x0','%l','Mix %x1','Add %x2','Subtract %x3','Multiply %x4','Difference %x5','Screen %x6','addmodulo %x7','Minimum %x8','Maximum %x9','%l','Warp Effect %x10','Warp Noise %x11'] +biastypemenu = "Bias %t|Sin bias %x0|Cos bias %x1|Tri bias %x2|Saw bias %x3|Default (no bias)%x4" +sharptypemenu = "Sharpen %t|Soft %x0|Sharp %x1|Sharper %x2" +filtermodemenu = "Filter Mode %t|No Filter %x0| %l|Default Filters %x1|IPOCurve Filter %x2|Custom Filter %x3" +filtertypemenu = "Filter Type %t|Default Terrace %x0|Sharper Terrace %x1|Rounded Terrace %x2|Posterise Mixed %x3|Posterise %x4|Layered Peaks %x5|Peaked %x6|Smooth-thing %x7|Sin bias %x8|Cos bias %x9|Tri bias %x10|Saw bias %x11|Clamp Max. %x12" +falloftypemenu = "Edge Falloff %t|No Edge Falloff %x0| %l|Soft Falloff %x1|Default Falloff %x2|Hard Falloff %x3|Linear Falloff Y %x4|Linear Falloff X %x5|Diagonal Falloff + %x6|Diagonal Falloff - %x7|Square %x8|Round %x9" +randomtypemenu = "Random type: %t|setRandomSeed() : Blender.Noise %x0|Rand() : Blender.Mathutils %x1|genrand() : BPyMathutils MersenneTwister %x2" + +##-------------------------------------------------- +def Set_ReSet_Values(): + global fileinfo, filemessage + global iScale, Offset, Invert, NSize, Sx, Sy, Lx, Ly, WorldSpaceCo + global NType, Basis, musgr, vlnoi, vlnoiTwo, voron, turbOne, turbTwo, marbleOne, marbleTwo, tBasismod, musgrTwo + global CustomFX, effect_image, Effect_Ctrl, Min, Max, Falloff, CustomFilt, Filter_Mode, Def_Filter_Ctrl, Ipo_Filter_Ctrl, Filter_Order + global RandMod, RSeed, rand_H, rand_S, rand_L, rand_I, AutoUpd, PreView, DefaultIpoName + + filemessage = '' + fileinfo = '' + effect_image = 'Load and Select image.' + AutoUpd = Create( 0 ) + PreView = [ Create( 0 ), Create( 1.0 ), Create( 0.0 ) ] + ## Coords controls: + WorldSpaceCo = Create(0) + iScale = [ Create( 1.0 ), Create( 1.0 ), Create( 0.25) ] + Offset = [ Create( 0.0 ), Create( 0.0), Create( 0.0) ] + Invert = [ Create( 0 ), Create( 0 ), Create( 0 ) ] + NSize = [ Create( 1.0 ), Create( 2.0 ) ] + Sx = [ Create( 1.0 ), Create( 1.0 ) ] + Sy = [ Create( 1.0 ), Create( 1.0 ) ] + Lx = [ Create( 0.0 ), Create( 0.0 ) ] + Ly = [ Create( 0.0 ), Create( 0.0 ) ] + ## Noise controls: + NType = Create( 3 ) + Basis = [ Create( 0 ), Create( 0 ) ] + musgr = [ Create( 1.0 ), Create( 2.0 ), Create( 8 ), Create( 1.0 ), Create( 1.0 ), Create( 0.5 ) ] + vlnoi = [ Create( 1.0 ), Create( 0 ) ] + vlnoiTwo = [ Create( 1.0 ), Create( 0 ) ] + voron = [ Create( 0 ), Create( 2.5 ) ] + turbOne = [ Create( 6 ), Create( 0 ), Create( 0.5 ), Create( 2.0 ) ] + marbleOne = [ Create( 6 ), Create( 0 ), Create( 2.0 ), Create( 0 ), Create( 0 ), Create( 1.0 ) ] + tBasismod = Create(0) + ## Effect controls: + musgrTwo = [ Create( 1.0 ), Create( 2.0 ), Create( 8 ), Create( 1.0 ), Create( 1.0 ) ] + turbTwo = [ Create( 6 ), Create( 0 ), Create( 0.5 ), Create( 2.0 ) ] + marbleTwo = [ Create( 6 ), Create( 0 ), Create( 2.0 ), Create( 0 ), Create( 0 ), Create( 1.0 ) ] + Effect_Ctrl = [ Create( 0 ),Create( 2 ),Create( 0.0 ),Create( 0 ),Create( 0.0 ) ,Create( 0 ),Create( 2.0 ),Create( 0.5 ),Create( 0.5 ) ] + CustomFX = [ Create('sin(x*pi)'), Create('cos(y*pi)'), Create('abs(a*b)*0.5') ] + ## Filter controls: + Min = Create( 0.0 ) + Max = Create( 1.0 ) + Falloff = [ Create( 2 ), Create( 1.0 ), Create( 1.0 ), Create( 0 ) , Create( 0 ) ] + Filter_Mode = Create( 0 ) + Def_Filter_Ctrl = [ Create( 0 ), Create( 3.0 ) ] + Ipo_Filter_Ctrl = [ Create( DefaultIpoName ), Create( 0 ), Create( 100.0 ), Create( 100.0 ) ] + Filter_Order = Create( 0 ) + CustomFilt = [ Create('sqrt(h*h)**2'), Create('0'), Create('a') ] + ## Randomise noise buttons: + RandMod = Create( 1 ) + RSeed = Create( 0 ) + rand_I = Create( 0 ) + rand_H = Create( 0 ) + rand_S = Create( 0 ) + rand_L = Create( 1 ) + +##------------------------- +Set_ReSet_Values() + + +####---------------------------------------------------------------------------------------------------- +###---------------------------------------------------------------------------------------------------- +## G.U.I.: text,backpanel,panel +#-------------------------------------------------- +def draw_Text( ( x, y ), text, color, size ): + glColor3f( color[0],color[1],color[2] ) + glRasterPos2d(x,y) + txtsize = 'small', 'normal', 'large' + Text( text, txtsize[ size ] ) +def draw_BackPanel( text, x, y, w, h, colors ): + glColor3f( colors[0]*0.76, colors[1]*0.76, colors[2]*0.76 ) + glRecti( x, h, w, h+20 ) + glColor3f( colors[0], colors[1], colors[2] ) + glRecti( x, y, w, h ) + glColor3f( colors[0], colors[1], colors[2] ) + glRasterPos2d( x+10, h+5 ) + Text( text, 'small' ) +def draw_Panel( x, y, w, h, colors ): + glColor3f( colors[0], colors[1], colors[2] ) + glRecti( x,y, w,h ) +def draw_Frame( text, x, y, w, h, color ): + glColor3f( color[0], color[1], color[2] ) + glRasterPos2i(x+3,h-3) + Text(text ,'small') + stringwidth = GetStringWidth( text,'small' ) + glColor3f( color[0], color[1], color[2] ) + glBegin(Blender.BGL.GL_LINE_STRIP) + glVertex2i(x,h) + glVertex2i(x,y) + glVertex2i(w,y) + glVertex2i(w,h) + glVertex2i(x+stringwidth+10,h) + glEnd() +def draw_Led( x, y, colors ): + glColor3f( colors[0], colors[1], colors[2] ) + glRecti( x,y, x+4,y+4 ) + + +###---------------------------------------------------------------------------------------------------- +## G.U.I. Buttons: +#---------------------------------------------------------------------------------------------------- + +###------------------------- +## Main / Mesh Buttons: +# +def MeshButtons( col, row, width, height ): + global actme, actob, AutoUpd, txtFile, filemessage, fileinfo + + PushButton("I", UseMe_Evt, col[8], row[3], width[0], height[1], "Info: Here you can write some text to save with the file." ) + draw_Text( ( col[0], row[1]+5 ), 'Info: ' + fileinfo, black, 0 ) + txtFile = String("", No_Evt, col[0], row[2], width[9], height[1], txtFile.val, 256, "File: Full path and filename" ) + PushButton( "Select", SelFile_Evt, col[1], row[3], width[0], height[1], "File: Open FileBrowser and select *.ant file" ) + PushButton( "Load", LoadFile_Evt,col[2], row[3], width[2], height[1], "File: Load settings from file ( HotKey: L )" ) + PushButton( "Save", SaveFile_Evt,col[5], row[3], width[2], height[1], "File: Save settings to file ( HotKey: S )" ) + + activeobname = '' + if actme !=[]: + activeobname = actob[0].name + draw_Text( ( col[5]+5, row[7]-5 ), 'OB: ' + activeobname, [0.0,0.0,1.0], 1 ) + PushButton( "Add New Grid", New_Evt, col[0], row[6], width[4], height[2] ) + PushButton( "Assign Selected", App_Evt, col[5], row[6], width[4], height[2], 'Assign selected terrain') + +###------------------------- +## Noise Buttons: +# +def NoiseButtons( col, row, width, height ): + global NSize, iScale, Offset, Invert, Lx, Ly, Sx, Sy, WorldSpaceCo + global Ha, La, Oc, Of, Ga, Basis, NType, musgr, vlnoi, voron, turbOne, tBasismod + global Depth, Hard, Amp, Freq, vlBasis, Distort, VFunc, VExp, VDep, marbleOne + global RandMod, RSeed, rand_H, rand_S, rand_L, rand_I + + bth = height[1]/2+5 + iScale[0] = Number("iScale:", Btn_Evt, col[5], row[2]+bth, width[3], height[1], iScale[0].val, -10.0, 10.0 , "Noise: Intensity Scale." ) + Invert[0] = Toggle("Inv.", Btn_Evt, col[9], row[2]+bth, width[0], height[1], Invert[0].val, "Noise: Invert") + Offset[0] = Number("Offset:", Btn_Evt, col[5], row[3]+bth, width[4], height[1], Offset[0].val, -10.0, 10.0 , "Noise: Offset " ) + NSize[0] = Number("Noise Size:",Btn_Evt, col[5], row[5], width[4], height[2], NSize[0].val, 0.001, 10.0 , "Noise Size" ) + Sx[0] = Number("Size X:", Btn_Evt, col[5], row[6], width[4], height[1], Sx[0].val, 0.001, 10.0 , "Size X" ) + Sy[0] = Number("Size Y:", Btn_Evt, col[5], row[7], width[4], height[1], Sy[0].val, 0.001, 10.0 , "Size Y" ) + Lx[0] = Number("Loc X:", Btn_Evt, col[5], row[8], width[4], height[1], Lx[0].val, -10000.0, 10000.0 , "Loc X" ) + Ly[0] = Number("Loc Y:", Btn_Evt, col[5], row[9],width[4], height[1], Ly[0].val, -10000.0, 10000.0 , "Loc Y" ) + WorldSpaceCo = Menu( "Coordinates %t|Local Space %x0|World Space %x1|Center at CursorPos %x2", Btn_Evt, col[5], row[10], width[4], height[1], WorldSpaceCo.val, "x,y,z coordinates for noise, effect and height falloff " ) + + NType = Menu( noisetypemenu, Btn_Evt, col[0], row[2], width[4], height[2], NType.val, "Noise type" ) + if NType.val == 6: + voron[0] = Menu( voronitypemenu, Btn_Evt, col[0], row[3], width[4], height[1], voron[0].val, "Voronoi type" ) + else: + if NType.val != 9: + Basis[0] = Menu( noisebasismenu, Btn_Evt, col[0], row[3], width[4], height[1], Basis[0].val, "Noise Basis" ) + + if NType.val in [0,1,2,3,4,11,12,13,14,15,17,18,19,20,21]: + musgr[0] = Slider( "H: ", Btn_Evt, col[0], row[5], width[4], height[1], musgr[0].val, 0.0, 3.0, 0 , "H" ) + musgr[1] = Slider( "Lacu: ", Btn_Evt, col[0], row[6], width[4], height[1], musgr[1].val, 0.0, 6.0, 0 , "Lacunarity" ) + musgr[2] = Slider( "Octs: ", Btn_Evt, col[0], row[4], width[4], height[1], musgr[2].val, 0, 12, 0 , "Octaves" ) + if NType.val in [1,2,3,13,14,15,18,19,20,21]: + musgr[3] = Slider( "Offst: ", Btn_Evt, col[0], row[7], width[4], height[1], musgr[3].val, 0.0, 6.0, 0 , "Offset" ) + if NType.val in [1,2,13,15,18]: + musgr[4] = Slider( "Gain: ", Btn_Evt, col[0], row[8], width[4], height[1], musgr[4].val, 0.0, 6.0, 0 , "Gain" ) + if NType.val == 19: + musgr[5] = Slider( "Thresh: ", Btn_Evt, col[0], row[8], width[4], height[1], musgr[5].val, 0.001, 2.0, 0 , "Threshold" ) + if NType.val in [5,6,7,16]: + turbOne[0] = Number( "Depth:", Btn_Evt, col[0], row[4], width[4], height[1], turbOne[0].val, 0, 12, "Octaves") + turbOne[1] = Toggle( "Hard noise", Btn_Evt, col[0], row[5], width[4], height[1], turbOne[1].val, "Soft noise / Hard noise") + turbOne[2] = Slider( "Amp:", Btn_Evt, col[0], row[6], width[4], height[1], turbOne[2].val, 0.0, 3.0, 0, "Ampscale ") + turbOne[3] = Slider( "Freq:", Btn_Evt, col[0], row[7], width[4], height[1], turbOne[3].val, 0.0, 6.0, 0, "Freqscale") + if NType.val in [18,19]: + tBasismod = Menu( tBasismodemenu, Btn_Evt, col[0], row[9], width[4], height[1], tBasismod.val, "Terrain basis mode.") + if NType.val == 6: + if voron[0].val == 6: + voron[1] = Slider( "Exp: ", Btn_Evt, col[0], row[8], width[4], height[1], voron[1].val, 0.0,10.0, 0, "Minkovsky exponent") + if NType.val in [7,11,12,14,20,21]: + vlnoi[0] = Slider( "Dist: ", Btn_Evt, col[0], row[8], width[4], height[1], vlnoi[0].val, 0.0, 10.0, 0 , "Distort" ) + if NType.val in [7,13,14,15,21]: + vlnoi[1] = Menu(noisebasismenu, Btn_Evt, col[0], row[9], width[4], height[1], vlnoi[1].val, "Distortion Noise") + if NType.val == 10: + marbleOne[0] = Number( "Depth: ", Btn_Evt, col[0], row[6], width[4], height[1], marbleOne[0].val, 0, 12, "Octaves") + marbleOne[2] = Slider( "Turb: ", Btn_Evt, col[0], row[7], width[4], height[1], marbleOne[2].val, 0.0,20.0, 0, "Turbulence ") + marbleOne[3] = Menu( biastypemenu, Btn_Evt ,col[0], row[4], width[4], height[1], marbleOne[3].val, "Bias") + marbleOne[5] = Slider("ReScale: ", Btn_Evt, col[0], row[8], width[4], height[1], marbleOne[5].val, 0.0,20.0, 0, "ReScale") + if marbleOne[3].val != 4: + marbleOne[4] = Menu(sharptypemenu, Btn_Evt ,col[0], row[5], width[4], height[1], marbleOne[4].val, "Sharpen") + + RandMod = Menu( randomtypemenu, No_Evt, col[0], row[10], width[0], height[1], RandMod.val, "Random Type" ) + rand_H = Toggle("TH",No_Evt ,col[1], row[10], width[0], height[1], rand_H.val, "Randomise Terrain Height ( in Height panel )") + rand_I = Toggle("NH",No_Evt ,col[2], row[10], width[0], height[1], rand_I.val, "Randomise Noise Height") + rand_S = Toggle("NS",No_Evt ,col[3], row[10], width[0], height[1], rand_S.val, "Randomise Noise Size") + rand_L = Toggle("NL",No_Evt ,col[4], row[10], width[0], height[1], rand_L.val, "Randomise Noise Location") + +###------------------------- +## Effect Buttons: +# +def EffectButtons( col, row, width, height ): + global Effect_Type, Effect_Ctrl, Blend_Effect, CustomFX + global NSize, iScale, Offset, Invert, Lx, Ly, Sx, Sy + global BasisTwo, turbTwo, marbleTwo, vlnoiTwo, musgrTwo + + Effect_Ctrl[0] = Menu( '|'.join( effecttypemenu ), Btn_Evt, col[0], row[2], width[4], height[2], Effect_Ctrl[0].val, "Effect: Type" ) + if Effect_Ctrl[0].val != 0: + Effect_Ctrl[1] = Menu( '|'.join( mixtypemenu ), Btn_Evt, col[5], row[2], width[4], height[2], Effect_Ctrl[1].val, "Mix: Type" ) + if Effect_Ctrl[1].val in [10,11]: + Effect_Ctrl[2] = Slider("Warp: ", Btn_Evt, col[5], row[3], width[4], height[1], Effect_Ctrl[2].val, -1.0, 1.0, 0, "Mix factor / Warp amount" ) + else: Effect_Ctrl[2] = Slider("Mix: ",Btn_Evt, col[5], row[3], width[4], height[1], Effect_Ctrl[2].val, -1.0, 1.0, 0, "Mix factor / Warp amount" ) + + iScale[1] = Number("iScale:", Btn_Evt, col[5], row[4], width[3], height[1], iScale[1].val, -20.0, 20.0 , "Effect: Intensity Scale " ) + Invert[1] = Toggle("Inv.", Btn_Evt, col[9], row[4], width[0], height[1], Invert[1].val, "Effect: Invert") + Offset[1] = Number("Offset:", Btn_Evt, col[5], row[5], width[4], height[1], Offset[1].val, -20.0, 20.0 , "Effect: Offset " ) + NSize[1] = Number("Frequency:",Btn_Evt, col[5], row[6], width[4], height[1], NSize[1].val, 0.001, 100.0, "Effect Frequency ( Scale )" ) + Sx[1] = Number("Freq X:", Btn_Evt, col[5], row[7], width[4], height[1], Sx[1].val, -50.0, 50.0 , "Effect Frequency X ( ScaleX )" ) + Sy[1] = Number("Freq Y:", Btn_Evt, col[5], row[8], width[4], height[1], Sy[1].val, -50.0, 50.0 , "Effect Frequency Y ( ScaleY )" ) + Lx[1] = Number("Loc X:", Btn_Evt, col[5], row[9], width[4], height[1], Lx[1].val, -1000.0, 1000.0 , "Effect Loc X" ) + Ly[1] = Number("Loc Y:", Btn_Evt, col[5], row[10], width[4], height[1], Ly[1].val, -1000.0, 1000.0 , "Effect Loc Y" ) + + if Effect_Ctrl[0].val == 1: + PushButton("Load Image", Load_Evt, col[0], row[4], width[4], height[2] , "Load Image") + PushButton("Select Image", Sel_Evt, col[0], row[6], width[4], height[3] , "Select Image") + draw_Text( ( col[0]+5, row[7] ), effect_image, black, 1 ) + + if Effect_Ctrl[0].val in [2,3,4,5,6,7,8,9]: + Basis[1] = Menu( noisebasismenu, Btn_Evt, col[0], row[3], width[4], height[1], Basis[1].val, "Basis" ) + + if Effect_Ctrl[0].val == 2: + turbTwo[0] = Number( "Depth:", Btn_Evt, col[0], row[4], width[4], height[1], turbTwo[0].val, 1, 12, "Octaves") + turbTwo[1] = Toggle("Hard noise", Btn_Evt, col[0], row[5], width[4], height[1], turbTwo[1].val, "Hard noise") + turbTwo[2] = Slider( "Amp:", Btn_Evt, col[0], row[6], width[4], height[1], turbTwo[2].val, 0.0, 3.0, 0, "Ampscale ") + turbTwo[3] = Slider( "Freq:", Btn_Evt, col[0], row[7], width[4], height[1], turbTwo[3].val, 0.0, 6.0, 0, "Freqscale") + if Effect_Ctrl[0].val == 3: + vlnoiTwo[1] = Menu(noisebasismenu, Btn_Evt, col[0], row[4], width[4], height[1], vlnoiTwo[1].val, "Distortion Noise") + vlnoiTwo[0] = Slider( "Dist: ", Btn_Evt, col[0], row[5], width[4], height[1], vlnoiTwo[0].val, 0.0, 10.0, 0 , "Distort" ) + if Effect_Ctrl[0].val == 4: + marbleTwo[0] = Number( "Depth: ", Btn_Evt, col[0], row[6], width[4], height[1], marbleTwo[0].val, 1, 12, "Octaves") + marbleTwo[2] = Slider( "Turb: ", Btn_Evt, col[0], row[7], width[4], height[1], marbleTwo[2].val, 0.0,20.0, 0, "Turbulence") + marbleTwo[3] = Menu( biastypemenu, Btn_Evt ,col[0], row[4], width[4], height[1], marbleTwo[3].val, "Bias") + marbleTwo[5] = Slider("ReScale: ", Btn_Evt, col[0], row[8], width[4], height[1], marbleTwo[5].val, 0.0,20.0, 0, "ReScale") + if marbleTwo[3].val != 4: + marbleTwo[4] = Menu(sharptypemenu,Btn_Evt ,col[0], row[5], width[4], height[1], marbleTwo[4].val, "Sharpen") + + if Effect_Ctrl[0].val in [5,6,7,8,9]: + musgrTwo[0] = Slider( "H: ", Btn_Evt, col[0], row[5], width[4], height[1], musgrTwo[0].val, 0.0, 3.0, 0 , "H" ) + musgrTwo[1] = Slider( "Lacu: ", Btn_Evt, col[0], row[6], width[4], height[1], musgrTwo[1].val, 0.0, 6.0, 0 , "Lacunarity" ) + musgrTwo[2] = Slider( "Octs: ", Btn_Evt, col[0], row[4], width[4], height[1], musgrTwo[2].val, 0, 12, 0 , "Octaves" ) + if Effect_Ctrl[0].val in [6,7,8]: + musgrTwo[3] = Slider( "Offst: ", Btn_Evt, col[0], row[7], width[4], height[1], musgrTwo[3].val, 0.0, 6.0, 0 , "Offset" ) + if Effect_Ctrl[0].val in [6,7]: + musgrTwo[4] = Slider( "Gain: ", Btn_Evt, col[0], row[8], width[4], height[1], musgrTwo[4].val, 0.0, 6.0, 0 , "Gain" ) + + if Effect_Ctrl[0].val > 9 and Effect_Ctrl[0].val < 31: + Effect_Ctrl[5] = Number("Depth:", Btn_Evt, col[0], row[4], width[4], height[1], Effect_Ctrl[5].val, 0, 12 , "Fractalize Effect: Octaves" ) + Effect_Ctrl[4] = Number("Distort:",Btn_Evt, col[0], row[7], width[4], height[1], Effect_Ctrl[4].val, 0.0, 50.0 , "Distort Effect: Amount" ) + Effect_Ctrl[6] = Slider("Freq:", Btn_Evt, col[0], row[5], width[4], height[1], Effect_Ctrl[6].val, 0.0, 6.0, 0, "Fractalize Effect: Frequency" ) + Effect_Ctrl[7] = Slider("Amp:", Btn_Evt, col[0], row[6], width[4], height[1], Effect_Ctrl[7].val, 0.0, 3.0, 0, "Fractalize Effect: Amplitude" ) + if Effect_Ctrl[0].val < 22: + Effect_Ctrl[3] = Menu(biastypemenu, Btn_Evt ,col[0], row[3], width[4], height[1], Effect_Ctrl[3].val, "Effect bias") + if Effect_Ctrl[0].val in [31,32]: + Effect_Ctrl[8] = Number("Amount:", Btn_Evt, col[0], row[4], width[4], height[1], Effect_Ctrl[8].val, -20.0, 20.0, "Effect: Amount" ) + if Effect_Ctrl[0].val == 33: + draw_Text( ( col[0]+5, row[4] ), 'Custom math ( h, x,y, a,b )' , black, 0 ) + CustomFX[0] = String( "a = ", Btn_Evt, col[0], row[5], width[4], height[1] ,CustomFX[0].val,96, "a" ) + CustomFX[1] = String( "b = ", Btn_Evt, col[0], row[6], width[4], height[1] ,CustomFX[1].val,96, "b" ) + CustomFX[2] = String( "result = ", Btn_Evt, col[0], row[7], width[4], height[1] ,CustomFX[2].val,96, "result" ) + +###------------------------- +## Filter / Height Buttons: +# +def FilterButtons( col, row, width, height ): + global iScale, Offset, Invert, Min, Max, Falloff, CustomFilt + global Filter_Mode, Def_Filter_Ctrl, Ipo_Filter_Ctrl, DefaultIpoName, Filter_Order + + iScale[2] = Number("Height:", Btn_Evt, col[5], row[2], width[3], height[2], iScale[2].val, -10.0, 10.0 , "Terrain Height: Scale" ) + Invert[2] = Toggle("Inv.", Btn_Evt, col[9], row[2], width[0], height[2], Invert[2].val, "Terrain Height: Invert") + Offset[2] = Number("Offset:", Btn_Evt, col[5], row[3], width[4], height[1], Offset[2].val, -10.0, 10.0 , "Terrain Height: Offset" ) + Max = Number( "Plateau:", Btn_Evt, col[5], row[5], width[4], height[1], Max.val, Min.val, 1.0 , "Terrain Height: Clamp Max. ( Plateau )" ) + Min = Number( "Sealevel:", Btn_Evt, col[5], row[6], width[4], height[1], Min.val, -1.0, Max.val , "Terrain Height: Clamp Min. ( Sealevel )" ) + Falloff[0] = Menu( falloftypemenu, Btn_Evt ,col[5], row[9], width[4], height[2], Falloff[0].val, "Terrain Height: Edge falloff") + if Falloff[0].val !=0: + Falloff[1] = Number("X:", Btn_Evt, col[5], row[10], width[1], height[1], Falloff[1].val , 0.01, 100.0 , "Edge falloff: X Size" ) + Falloff[2] = Number("Y:", Btn_Evt, col[8], row[10], width[1], height[1], Falloff[2].val , 0.01, 100.0 , "Edge falloff: Y Size" ) + Falloff[4] = Toggle("Inv.", Btn_Evt, col[7], row[10], width[0], height[1], Falloff[4].val, "Edge falloff: Invert") + Falloff[3] = Toggle("Edge At Sealevel", Btn_Evt, col[5], row[7], width[4], height[1], Falloff[3].val, "Edge falloff: Edge at Sealevel") + + Filter_Mode = Menu( filtermodemenu, No_Evt, col[0], row[2], width[4], height[2], Filter_Mode.val, "Filter: Mode") + if Filter_Mode.val ==1: + Def_Filter_Ctrl[0] = Menu( filtertypemenu, Btn_Evt, col[0], row[5], width[4], height[2], Def_Filter_Ctrl[0].val, "Filter: Type") + Def_Filter_Ctrl[1] = Number("Amount: ", Btn_Evt, col[0], row[6], width[4], height[1], Def_Filter_Ctrl[1].val, 0.1, 100.0 , "Filter: Amount" ) + + if Filter_Mode.val ==2: + Ipo_Filter_Ctrl[0] = String("IP:", Ipo_Evt, col[0], row[5], width[4], height[2], Ipo_Filter_Ctrl[0].val,20, "Ipo datablock name" ) + if Ipo_Filter_Ctrl[0].val !='': + Ipo_Filter_Ctrl[1] = Number("Use This Curve:",Ipo_Evt, col[0], row[7], width[4], height[3], Ipo_Filter_Ctrl[1].val, 0, 29, "Select curve to use" ) + Ipo_Filter_Ctrl[2] = Number("Curve Length:", Ipo_Evt, col[0], row[8], width[4], height[1], Ipo_Filter_Ctrl[2].val, 0.0, 1000.0, "X: Length (number of frames) of the selected curve." ) + Ipo_Filter_Ctrl[3] = Number("Curve Height:", Ipo_Evt, col[0], row[9], width[4], height[1], Ipo_Filter_Ctrl[3].val, 0.0, 1000.0, "Y: Height (offset) of the selected curve." ) + else: + draw_Text( ( col[0]+5, row[6] ), 'Enter Ipo DataBlock name,' , black, 0 ) + draw_Text( ( col[0]+5, row[9] ), 'or else:' , black, 0 ) + PushButton( "New IpoDataBlock/Object", New_Ipo_Evt, col[0], row[10], width[4], height[1], "Creates new Ipo Object(Empty), and Ipo DataBlock(curves)' to use as height filter") + + if Filter_Mode.val ==3: + draw_Text( ( col[0]+5, row[4] ), 'Custom math ( h, x,y, a,b )' , black, 0 ) + CustomFilt[0] = String( "a = ", Btn_Evt, col[0], row[5], width[4], height[1] ,CustomFilt[0].val,96, "a" ) + CustomFilt[1] = String( "b = ", Btn_Evt, col[0], row[6], width[4], height[1] ,CustomFilt[1].val,96, "b" ) + CustomFilt[2] = String( "result = ", Btn_Evt, col[0], row[7], width[4], height[1] ,CustomFilt[2].val,96, "result" ) + if Filter_Mode.val !=0: + Filter_Order = Toggle("Change Filter Order", Btn_Evt, col[0], row[3], width[4], height[1], Filter_Order.val, "Filter Order: OFF = Noise+Effect+Falloff+FILTER / ON = Noise+FILTER+Effect+Falloff.") + +###------------------------- +## Option / Generate Image Buttons: +# +def OptionButtons( col, row, width, height ): + global PreView, previewname + + PreView[0] = Toggle("Make Image", No_Evt, col[0], row[2], width[4], height[2], PreView[0].val, "Image: On/Off (Make a new Image in UV/ImageEditor Window, and give a name to it)") + if PreView[0].val !=0: + previewname = String( "IM:", No_Evt, col[0], row[3], width[4], height[1] ,previewname.val, 16, "IM:Name, Render terrain height to this image" ) + PreView[1] = Number("", Im_Evt, col[0], row[4], width[1], height[1], PreView[1].val, 0.0, 10.0, "Image: Intensity Scale") + PreView[2] = Number("", Im_Evt, col[3], row[4], width[1], height[1], PreView[2].val,-10.0, 10.0, "Image: Offset") + PushButton( "Draw Image", Im_Evt, col[0], row[5], width[4], height[1] , "Image: Update image ( KEY: V )") + draw_Text( ( col[5], row[1] ), 'Create yourself a new image', black, 0 ) + draw_Text( ( col[5], row[2] ), 'in UV/Image Editor Window,', black, 0 ) + draw_Text( ( col[5], row[3] ), 'give it a name,', black, 0 ) + draw_Text( ( col[5], row[4] ), 'and save it manualy.', black, 0 ) + +####-------------------------------------------------------------------------- +###-------------------------------------------------------------------------- +## Draw G.U.I. ------------------------------------------------------------- +#-------------------------------------------------------------------------- +def drawgui(): + global guitabs, ledcolor, FullScreen, AutoUpd, RandMod, RSeed, filemessage + global Effect_Ctrl, Filter_Mode, Falloff, PreView, rand_H, rand_S, rand_L, rand_I + + glClearColor(background[0],background[1],background[2],background[3]) + glClear(GL_COLOR_BUFFER_BIT) + scissorbox=Buffer(GL_FLOAT,4) + glGetFloatv(GL_SCISSOR_BOX,scissorbox) + scissbleft=int(scissorbox[0]) + scissbbase=int(scissorbox[1]) + scissbwidth=int(scissorbox[2]) + scissbheight=int(scissorbox[3]) + xstart = 5 + ystart = 5 + xgap = 5 + ygap = 5 + if FullScreen.val==1: + guiwidth = scissbwidth-10 + guiheight = scissbheight-25 + if guiwidth < size_x/2: + guiwidth = size_x/2 + if guiheight < size_y/2: + guiheight = size_y/2 + else: + guiwidth = size_x + guiheight = size_y + col,row = [],[] + xpart = ( ( guiwidth-xstart ) / columns ) + ypart = ( ( guiheight-ystart ) / rows ) + width = [] + for c in xrange( columns ): + col.append( xgap + xpart * c + xstart ) + width.append( xpart*(c+1)-xgap ) + height = [ (ypart-ygap)/2 , ypart-ygap, (ypart*3-ygap)/2, ypart*2-ygap, (ypart*5-ygap)/2 ] + for r in xrange( rows ): + row.append( ygap + ypart * r + ystart ) + row.reverse() + + ###------------------------- + ## Draw G.U.I.: + draw_BackPanel( 'Another Noise Tool 1.05', xstart, ystart, guiwidth, guiheight + ygap, lightgrey ) + + FullScreen = Toggle("", Scrn_Evt, guiwidth-32, guiheight+ygap+3, 15, 15, FullScreen.val ,"FullScreen" ) + PushButton( "X", End_Evt, guiwidth-16, guiheight+ygap+3, 15, 15, "Exit" ) + draw_Text(( guiwidth-(guiwidth/2)-width[0], guiheight+ygap+5 ), filemessage, white, 0 ) + + # gui tabs + guitabs[0] = Toggle("Main", gt0_Evt, col[0], row[0], width[1], height[1], guitabs[0].val ,"Main / Mesh settings" ) + guitabs[1] = Toggle("Noise", gt1_Evt, col[2], row[0], width[1], height[1], guitabs[1].val ,"Noise settings" ) + guitabs[2] = Toggle("Effect", gt2_Evt, col[4], row[0], width[1], height[1], guitabs[2].val ,"Add Effect" ) + guitabs[3] = Toggle("Height", gt3_Evt, col[6], row[0], width[1], height[1], guitabs[3].val ,"Height Filter" ) + guitabs[4] = Toggle("Options", gt4_Evt, col[8], row[0], width[1], height[1], guitabs[4].val ,"Options" ) + + if guitabs[0].val !=0: MeshButtons( col, row, width, height ) + elif guitabs[1].val !=0: NoiseButtons( col, row, width, height ) + elif guitabs[2].val !=0: EffectButtons( col, row, width, height ) + elif guitabs[3].val !=0: FilterButtons( col, row, width, height ) + elif guitabs[4].val !=0: OptionButtons( col, row, width, height ) + else: # some info + draw_Panel( col[0], row[0]-5, col[9]+width[0], row[10]-10, black ) + draw_Text( ( col[0]+5, row[1] ), 'Another Noise Tool v.1.05', ledcolors[0], 2 ) + draw_Text( ( col[0]+5, row[2] ), 'by: Jimmy Hazevoet, 01/2005-03/2007', ledcolors[1], 2 ) + draw_Text( ( col[0]+5, row[3] ), 'v.1.05: build/tested in: Blender 2.43 (Wndws)', ledcolors[2], 1 ) + draw_Text( ( col[0]+5, row[4] ), 'HotKeys: ----------------------------', ledcolors[3], 2 ) + draw_Text( ( col[0]+5, row[5] ), 'Space = Update mesh', ledcolors[4], 2 ) + draw_Text( ( col[0]+5, row[6] ), 'V = Update Image', ledcolors[5], 2 ) + draw_Text( ( col[0]+5, row[7] ), 'R = Randomise', ledcolors[6], 2 ) + draw_Text( ( col[0]+5, row[8] ), 'L = Load from file', ledcolors[7], 2 ) + draw_Text( ( col[0]+5, row[9] ), 'S = Save to file', ledcolors[8], 2 ) + draw_Text( ( col[0]+5, row[10] ),'Q = Quit', ledcolors[9], 2 ) + + # auto/generate/randomise buttons + rand_on_off = 0 + if rand_H.val !=0: rand_on_off = 1 + elif rand_I.val !=0: rand_on_off = 1 + elif rand_S.val !=0: rand_on_off = 1 + elif rand_L.val !=0: rand_on_off = 1 + else: rand_on_off = 0 + if rand_on_off != 0: + if RandMod.val in [1,2]: + PushButton( "Randomise", Rndm_Evt, col[2], row[12], width[2], height[2] , "Randomise Noise ( KEY: R )") + else: RSeed = Number("Seed: ", Rndm_Evt, col[2], row[12], width[2], height[2], RSeed.val, 0, 255 , "Random Seed: If seed = 0, the current time will be used as seed." ) + AutoUpd = Toggle("Auto", No_Evt, col[0], row[12], width[1], height[2], AutoUpd.val ,"Automatic update" ) + PushButton("Update", Upd_Evt, col[5], row[12], width[4], height[2] , "Generate / Update. ( KEY: SPACE )") + else: + AutoUpd = Toggle("Auto", No_Evt, col[0], row[12], width[1], height[2], AutoUpd.val ,"Automatic update" ) + PushButton("Update", Upd_Evt, col[2], row[12], width[7], height[2] , "Generate / Update. ( KEY: SPACE )") + ####--------------------------------------------------------------------------- + +###--------------------------------------------------------------------------- +##--------------------------------------------------------------------------- +# Key Events: + +def events(evt, val): + global PreView, txtFile, AutoUpd, PreView + + ## hotkey: Q = Quit + if (evt == QKEY and not val): + name = "Quit ?%t|No %x0|Yes %x1" + result = Blender.Draw.PupMenu(name) + if result==1: + Exit() + + ## hotkey: Space = Generate/Update terrain + if (evt == SPACEKEY and not val): + do_it() + + ## hotkey: R = Randomise noise + if (evt in [ RKEY ] and not val): + if AutoUpd.val != 0: + do_it_random() + else: + randomiseNoise() + Draw() + + ## hotkey: V = Update image + if PreView[0].val != 0: + if (evt in [ VKEY, RKEY ] and not val): + do_it_preview() + + ## hotkey: L = Load from file + if (evt == LKEY and not val): + loadmenu = "Load file ?%t|" + txtFile.val + loadresult = Blender.Draw.PupMenu(loadmenu) + if loadresult==1: + LoadPreset(txtFile.val) + if AutoUpd.val != 0: + do_it() + else: Draw() + + ## hotkey: S = Save to file + if (evt == SKEY and not val): + savemenu = "Save file ?%t|" + txtFile.val + saveresult = Blender.Draw.PupMenu(savemenu) + if saveresult==1: + SavePreset(txtFile.val) + Draw() + +###--------------------------------------------------------------------------- +##--------------------------------------------------------------------------- +# Button events: + +def bevents(evt): + global txtFile, effect_image, PreView, fileinfo, filemessage + global Filter_Mode, Ipo_Filter_Ctrl, iponame, thiscurve, selectedcurve + global antfilename, terrainname + global actob, actme + + # quit/reset event + if (evt == End_Evt ): + name = "OK ?%t|Reset %x1|Quit %x2" + result = Blender.Draw.PupMenu(name) + if result==1: + Set_ReSet_Values() + Draw() + elif result==2: + Exit() + + ## file info string event + if (evt == UseMe_Evt ): + result = Blender.Draw.PupStrInput("Info: ", fileinfo, 96) + if result: + fileinfo = result + Draw() + else: return + + ## none event + if (evt in [No_Evt, Scrn_Evt] ): + Draw() + + ## image event + if (evt == Im_Evt ): + do_it_preview() + + ## generate/update event + if (evt == Upd_Evt ): + if PreView[0].val != 0: + do_it_preview() + do_it() + + ## mesh button event + if (evt == Msh_Evt): + if AutoUpd.val != 0: + do_it() + else: Draw() + + ## button event + if (evt == Btn_Evt ): + if AutoUpd.val != 0: + if PreView[0].val != 0: + do_it_preview() + do_it() + else: Draw() + + ## randomise event + if (evt == Rndm_Evt ): + if AutoUpd.val != 0: + do_it_random() + else: + randomiseNoise() + if PreView[0].val != 0: + do_it_preview() + Draw() + + ###--------------------------------------------------------- + ## Effect Image Load/Select: + if (evt == Load_Evt ): + Blender.Window.FileSelector ( load_image, 'LOAD IMAGE') + if (evt == Sel_Evt ): + try: effect_image = Image_Menu() + except: pass + if AutoUpd.val != 0: + do_it() + else: Draw() + + ###--------------------------------------------------------- + ## Make New IPOCurve to use as Filter: + if (evt == New_Ipo_Evt ): + objname = Create("ANT_Ipo_Empty") + iponame = Create("ANT_IPO") + block = [] + block.append("Enter new names") + block.append("and hit OK button") + block.append(("OB: ", objname, 0, 30, "New Ipo Object Name. (Object type = 'Empty')")) + block.append(("IP: ", iponame, 0, 30, "New Ipo DataBlock Name")) + block.append("Open IpoCurveEditor") + block.append("select Ipo DataBlock" ) + block.append("'Pin' the view" ) + block.append("and edit the curves." ) + retval = PupBlock("Make A.N.T. IpoCurve Object", block) + if retval !=0: + ANTAutoIpo( objname.val, iponame.val ) + Ipo_Filter_Ctrl[0].val = iponame.val + + ###--------------------------------------------------------- + ## get IPOCurve to use as Filter: + if (evt in [Ipo_Evt, New_Ipo_Evt] ): + if Filter_Mode.val == 2: + if AutoUpd.val != 0: + try: + ipoblockname = Ipo.Get( Ipo_Filter_Ctrl[0].val ) + thiscurve = ipoblockname.getCurves() + selectedcurve = thiscurve[ Ipo_Filter_Ctrl[1].val ] + if PreView[0].val != 0: + do_it_preview() + #if AutoUpd.val != 0: + do_it() + except: pass + else: + try: + ipoblockname = Ipo.Get( Ipo_Filter_Ctrl[0].val ) + thiscurve = ipoblockname.getCurves() + selectedcurve = thiscurve[ Ipo_Filter_Ctrl[1].val ] + if PreView[0].val != 0: + do_it_preview() + else: + Draw() + except: pass + + ###--------------------------------------------------------- + ## gui tabs + if (evt == gt0_Evt ): + if guitabs[0].val == 1: + guitabs[1].val = ( 0 ) + guitabs[2].val = ( 0 ) + guitabs[3].val = ( 0 ) + guitabs[4].val = ( 0 ) + Draw() + if (evt == gt1_Evt ): + if guitabs[1].val == 1: + guitabs[0].val = ( 0 ) + guitabs[2].val = ( 0 ) + guitabs[3].val = ( 0 ) + guitabs[4].val = ( 0 ) + Draw() + if (evt == gt2_Evt ): + if guitabs[2].val == 1: + guitabs[0].val = ( 0 ) + guitabs[1].val = ( 0 ) + guitabs[3].val = ( 0 ) + guitabs[4].val = ( 0 ) + Draw() + if (evt == gt3_Evt ): + if guitabs[3].val == 1: + guitabs[0].val = ( 0 ) + guitabs[1].val = ( 0 ) + guitabs[2].val = ( 0 ) + guitabs[4].val = ( 0 ) + Draw() + if (evt == gt4_Evt ): + if guitabs[4].val == 1: + guitabs[0].val = ( 0 ) + guitabs[1].val = ( 0 ) + guitabs[2].val = ( 0 ) + guitabs[3].val = ( 0 ) + Draw() + + ###--------------------------------------------------------- + ## load and save all settings: + if (evt == SelFile_Evt ): + Blender.Window.FileSelector ( callback, "Select .ant File") + if (evt == LoadFile_Evt ): + loadmenu = "Load file ?%t|" + txtFile.val + loadresult = Blender.Draw.PupMenu(loadmenu) + if loadresult==1: + LoadPreset(txtFile.val) + Draw() + if AutoUpd.val != 0: + do_it() + if (evt == SaveFile_Evt ): + savemenu = "Save file ?%t|" + txtFile.val + saveresult = Blender.Draw.PupMenu(savemenu) + if saveresult==1: + SavePreset(txtFile.val) + Draw() + + ###--------------------------------------------------------- + # New Grid + ###------------------------- + if (evt == New_Evt): + scn = Blender.Scene.GetCurrent() + gridname = Create("Terrain") + gridres = Create(256) + curspos = Create(0) + block = [] + block.append(("OB: ", gridname, 0, 30, "New Object Name.")) + block.append(("Resol: ", gridres, 4, 1024, "New grid resolution")) + block.append(("At Cursor", curspos, "New grid at cursor position")) + retval = PupBlock("New Grid Mesh", block) + if retval !=0: + MakeGridMesh( gridres.val, gridname.val, curspos.val, scn ) + obj = scn.objects.active + if obj.type == 'Mesh': + actob=[] + actme=[] + actob.append( obj ) + actme.append( actob[0].getData(mesh=1) ) + Blender.Redraw() + + ###--------------------------------------------------------- + # Assign Grid + ###------------------------- + if (evt == App_Evt): + scn = Blender.Scene.GetCurrent() + obj = scn.objects.active + if obj: + if obj.type == 'Mesh': + actob=[] + actme=[] + actob.append( obj ) + actme.append( actob[0].getData(mesh=1) ) + Draw() + + ###------------------------- + if (evt not in [LoadFile_Evt,SaveFile_Evt] ): + filemessage = '' + #Draw() + + ### end events. ------------------------- + +####------------------------------------------------------------------------------------- +###------------------------------------------------------------------------------------- +##------------------------------------------------------------------------------------- +#------------------------------------------------------------------------------------- + +##---------------------------------- +# A.N.T. Auto Ipo generator: +def ANTAutoIpo( objname, iponame ): + scn=Scene.GetCurrent() + # Deselect all objects: + scn.objects.selected=[] + # Create new 'ANT_IPO_OBJECT': + obj = scn.objects.new('Empty', objname ) + obj.setDrawMode(8) + obj.select(1) + obj.layers = Window.ViewLayers() + # Set current frame at 1: + frame = Get('curframe') + if frame !=1: + Set('curframe',1) + frame = Get('curframe') + # Insert IpoKeys: + obj.setLocation(0.0, 0.0, 0.0) + obj.insertIpoKey(0) + Set('curframe',101) + obj.setLocation(100.0, 100.0, 100.0) + obj.insertIpoKey(0) + Set('curframe',1) + # Set Ipo name: + ip = obj.getIpo() + ip.name = iponame + #------------------------- + print "New ANT_IPO: " + objname +" (Object) and " + iponame + " (Ipo DataBlock) Created!" + #------------------------- + +##------------------------------------------------------------------------------------- + +##------------------------- +# Generate random numbers: +def randnum(low,high): + global RandMod, RSeed + if RandMod.val == 0: + # Noise.random setRandomSeed + s = Noise.setRandomSeed( RSeed.val ) + num = Noise.random() + num = num*(high-low) + num = num+low + elif RandMod.val == 1: + # Mathutils.Rand + num = Mathutils.Rand(low,high) + else: + # BPyMathutils Mersenne Twister genrand + num = genrand() + num = num*(high-low) + num = num+low + return num + +##------------------------- +# Randomise noise: height, size and location: +def randomiseNoise(): + global rand_I, rand_H, rand_S, rand_L, NSize, iScale, Offset, Invert, Lx, Ly, Sx, Sy + + if rand_I.val !=0: + iScale[0] = Create( randnum( 0.2 , 3.0 ) ) + Offset[0] = Create( randnum(-1.0 , 1.0 ) ) + if rand_H.val !=0: + iScale[2] = Create( randnum( 0.10 , 1.0 ) ) + Offset[2] = Create( randnum(-0.25 , 0.25 ) ) + if rand_S.val !=0: + NSize[0] = Create( randnum( 0.25 , 2.5 ) ) + #Sx[0] = Create( randnum( 0.5 , 1.5 ) ) + #Sy[0] = Create( randnum( 0.5 , 1.5 ) ) + if rand_L.val !=0: + Lx[0] = Create( randnum( -10000 , 10000 ) ) + Ly[0] = Create( randnum( -10000 , 10000 ) ) + +##------------------------------------------------------------------------------------- + +###-------------------------- +# Load Image: +def load_image( ImageFileName ): + Image.Load( ImageFileName ) + +###-------------------------- +# Select Image Menu: +def Image_Menu(): + try: + names=[] + imagelist = Image.Get() + imagelist.reverse() + for numbers, obnames in enumerate( imagelist ): + n = obnames.getName() + names.append( n ) + imlistText = string.join( [ '|' + str(names[key]) + '%x' + str(key) for key in xrange(numbers+1) ], '' ) + image_menu = Blender.Draw.PupMenu( "Images: %t" + imlistText ) + if image_menu == -1: + return '' + return imagelist[ image_menu ].getName() + except: + return 'No image found!' + +###-------------------------- +# Get Image Pixels: +def Image_Func( x,y ): + try: + pic = Image.Get( effect_image ) + except: + return 0.0 + w, h = pic.getSize() + x, y = x,-y + x = int(w * ((x + 1.0) % 2.0) / 2.0) + y = int((h-1) - h * ((y + 1.0) % 2.0) / 2.0) + c = pic.getPixelF( x,y ) + return ( c[0] + c[1] + c[2] ) / 3.0 + +##------------------------------------------------------------------------------------- + +# Transpose noise coords: +def Trans((x,y,z), size, loc ): + x = ( x / size[1] / size[0] + loc[0] ) + y = ( y / size[2] / size[0] + loc[1] ) + z = 0.0 #( z / size[3] / size[0] + loc[2] ) + return x,y,z + +# Transpose effect coords: +def Trans_Effect((x,y,z), size, loc ): + x = ( x * size[1] * size[0] + loc[0] ) + y = ( y * size[2] * size[0] + loc[1] ) + z = 0.0 + return x,y,z + +# Height scale: +def HeightScale( input, iscale, offset, invert ): + if invert !=0: + return (1.0-input) * iscale + offset + else: + return input * iscale + offset + +# dist. +def Dist(x,y): + return sqrt( (x*x)+(y*y) ) + +##----------------------------------- +# bias types: +def no_bias(a): + return a +def sin_bias(a): + return 0.5 + 0.5 * sin(a) +def cos_bias(a): + return 0.5 + 0.5 * cos(a) +def tri_bias(a): + b = 2 * phi + a = 1 - 2 * abs(floor((a * (1/b))+0.5) - (a*(1/b))) + return a +def saw_bias(a): + b = 2 * phi + n = int(a/b) + a -= n * b + if a < 0: a += b + return a / b +# sharpen types: +def soft(a): + return a +def sharp(a): + return a**0.5 +def sharper(a): + return sharp(sharp(a)) +Bias_Types = [ sin_bias, cos_bias, tri_bias, saw_bias, no_bias ] +Sharp_Types = [ soft, sharp, sharper ] + +##----------------------------------- +# clamp height +def clamp( height, min, max ): + if ( height < min ): height = min + if ( height > max ): height = max + return height + +##----------------------------------- +# Mix modes +def maximum( a, b ): + if ( a > b ): b = a + return b +def minimum( a, b ): + if ( a < b ): b = a + return b + +def Mix_Modes( (i,j),(x,y,z) , a,b, mixfactor, mode ): + a = a * ( 1.0 - mixfactor ) + b = b * ( 1.0 + mixfactor ) + if mode == 0: return ( b ) #0 effect only + elif mode == 1: return ( a*(1.0-0.5) + (b*0.5) ) #1 mix + elif mode == 2: return ( a + b ) #2 add + elif mode == 3: return ( a - b ) #3 sub. + elif mode == 4: return ( a * b ) #4 mult. + elif mode == 5: return (abs( a - b )) #5 abs diff. + elif mode == 6: return 1.0-((1.0-a)*(1.0-b)/1.0) #6 screen + elif mode == 7: return ( a + b ) % 1.0 #7 addmodulo + elif mode == 8: return min( a, b ) #8 min. + elif mode == 9: return max( a, b ) #9 max. + elif mode == 10: #10 warp: effect + noise = mixfactor * Noise_Function(x,y,z) + return Effects( (i,j),(x+noise,y+noise,z) ) + elif mode == 11: #11 warp: noise + effect = mixfactor * Effects( (i,j),(x,y,z) ) + return Noise_Function( x+effect, y+effect, z ) + else: return a + +###---------------------------------------------------------------------- +# Effect functions: + +# Effect_Basis_Function: +def Effect_Basis_Function((x,y), type, bias ): + + iscale = 1.0 + offset = 0.0 + ## gradient: + if type == 0: + effect = offset + iscale * ( Bias_Types[ bias ]( x + y ) ) + ## waves / bumps: + if type == 1: + effect = offset + iscale * 0.5 * ( Bias_Types[ bias ]( x*phi ) + Bias_Types[ bias ]( y*phi ) ) + ## zigzag: + if type == 2: + effect = offset + iscale * Bias_Types[ bias ]( offset + iscale * sin( x*phi + sin( y*phi ) ) ) + ## wavy: + if type == 3: + effect = offset + iscale * ( Bias_Types[ bias ]( cos( x ) + sin( y ) + cos( x*2+y*2 ) - sin( -x*4+y*4) ) ) + ## sine bump: + if type == 4: + effect = offset + iscale * 1-Bias_Types[ bias ](( sin( x*phi ) + sin( y*phi ) )) + ## dots: + if type == 5: + effect = offset + iscale * ( Bias_Types[ bias ](x*phi*2) * Bias_Types[ bias ](y*phi*2) )-0.5 + ## rings / dome: + if type == 6: + effect = offset + iscale * ( Bias_Types[ bias ]( 1.0-(x*x+y*y) ) ) + ## spiral: + if type == 7: + effect = offset + iscale * Bias_Types[ bias ](( x*sin( x*x+y*y ) + y*cos( x*x+y*y ) ))*0.5 + ## square / piramide: + if type == 8: + effect = offset + iscale * Bias_Types[ bias ](1.0-sqrt( (x*x)**10 + (y*y)**10 )**0.1) + ## blocks: + if type == 9: + effect = ( 0.5-max( Bias_Types[ bias ](x*phi) , Bias_Types[ bias ](y*phi) )) + if effect > 0.0: effect = 1.0 + effect = offset + iscale * effect + ## grid: + if type == 10: + effect = ( 0.025-min( Bias_Types[ bias ](x*phi) , Bias_Types[ bias ](y*phi) )) + if effect > 0.0: effect = 1.0 + effect = offset + iscale * effect + ## tech: + if type == 11: + a = ( max( Bias_Types[ bias ](x*pi) , Bias_Types[ bias ](y*pi) )) + b = ( max( Bias_Types[ bias ](x*pi*2+2) , Bias_Types[ bias ](y*pi*2+2) )) + effect = ( min( Bias_Types[ bias ](a) , Bias_Types[ bias ](b) ))*3.0-2.0 + if effect > 0.5: effect = 1.0 + effect = offset + iscale * effect + + ## crackle: + if type == 12: + t = turbulence(( x, y, 0 ), 6, 0, 0 ) * 0.25 + effect = vlNoise(( x, y, t ), 0.25, 0, 8 ) + if effect > 0.5: effect = 0.5 + effect = offset + iscale * ( effect ) + ## sparse cracks noise: + if type == 13: + effect = 2.5 * abs( noise((x*0.5,y*0.5, 0 ), 1 ) )-0.1 + if effect > 0.25: effect = 0.25 + effect = offset + iscale * ( effect * 2.5 ) + ## shattered rock noise: + if type == 14: + effect = 0.5 + noise((x,y,0), 7 ) + if effect > 0.75: effect = 0.75 + effect = offset + iscale * effect + ## lunar noise: + if type == 15: + effect = 0.25 + 1.5 * voronoi(( x+2, y+2, 0 ), 1 )[0][0] + if effect > 0.5: effect = 0.5 + effect = offset + iscale * ( effect * 2.0 ) + ## cosine noise: + if type == 16: + effect = cos( 5*noise(( x, y, 0 ), 0 ) ) + effect = offset + iscale * ( effect*0.5 ) + ## spikey noise: + if type == 17: + n = 0.5 + 0.5 * turbulence(( x*5, y*5, 0 ), 8, 0, 0 ) + effect = ( ( n*n )**5 ) + effect = offset + iscale * effect + ## stone noise: + if type == 18: + effect = offset + iscale *( noise((x*2,y*2, 0 ), 0 ) * 1.5 - 0.75) + ## Flat Turb: + if type == 19: + t = turbulence(( x, y, 0 ), 6, 0, 0 ) + effect = t*2.0 + if effect > 0.25: effect = 0.25 + effect = offset + iscale * ( effect ) + ## Flat Voroni: + if type == 20: + t = 1-noise(( x, y, 0 ), 3 ) + effect = t*2-1.75 + if effect > 0.25: effect = 0.25 + effect = offset + iscale * ( effect ) + + if effect < 0.0: effect = 0.0 + return effect + +# fractalize Effect_Basis_Function: ------------------------------ +def Effect_Function((x,y), type,bias, turb, depth,frequency,amplitude ): + + ## effect distortion: + if turb != 0.0: + t = vTurbulence(( x, y, 0 ), 6, 0, 0 ) + x = x + ( 0.5 + 0.5 * t[0] ) * turb + y = y + ( 0.5 + 0.5 * t[1] ) * turb + + result = Effect_Basis_Function((x,y), type, bias ) + ## fractalize effect: + if depth != 0: + i=0 + while i < depth: + i+=1 + x *= frequency + y *= frequency + amplitude = amplitude / i + result += Effect_Basis_Function( (x,y), type, bias ) * amplitude + return result + +###-------------------------------------------------- +# Custom effect: +def CustomEffect( x,y,z,h ): + global CustomFX + try: + a = eval( CustomFX[0].val ) + b = eval( CustomFX[1].val ) + result = eval( CustomFX[2].val ) + return result + except: + return 0.0 + +###-------------------------------------------------- +## Effect Selector: + +def Effects( (i,j),(x,y,z), h=0.0 ): + global Effect_Type, Effect_Ctrl, iScale, Offset, Invert + global NSize, Lx, Ly, Lz, Sx, Sy, Sz, marbleTwo, turbTwo, vlnoiTwo, Basis, musgrTwo + + x,y,z = Trans_Effect((x,y,z),( NSize[1].val, Sx[1].val, Sy[1].val, 0 ),( Lx[1].val, Ly[1].val, 0 ) ) + basis = Basis[1].val + if basis == 9: basis = 14 + vbasis = vlnoiTwo[1].val + if vbasis == 9: vbasis = 14 + if Effect_Ctrl[0].val == 1: + try: effect = Image_Func( x,y ) + except: effect = 0.0 + elif Effect_Ctrl[0].val == 2: effect = 0.5+0.5*turbulence(( x,y,z ),turbTwo[0].val, turbTwo[1].val, basis, turbTwo[2].val, turbTwo[3].val ) + elif Effect_Ctrl[0].val == 3: effect = 0.5+0.5*vlNoise(( x,y,z ),vlnoiTwo[0].val, vbasis, basis ) + elif Effect_Ctrl[0].val == 4: effect = 0.5*marbleNoise((x,y,z), marbleTwo[0].val, basis, marbleTwo[2].val, marbleTwo[3].val, marbleTwo[4].val, marbleTwo[5].val ) + elif Effect_Ctrl[0].val == 5: effect = 0.5*multiFractal(( x,y,z ),musgrTwo[0].val, musgrTwo[1].val, musgrTwo[2].val, basis ) + elif Effect_Ctrl[0].val == 6: effect = 0.5*ridgedMFractal(( x,y,z ),musgrTwo[0].val, musgrTwo[1].val, musgrTwo[2].val, musgrTwo[3].val, musgrTwo[4].val, basis ) + elif Effect_Ctrl[0].val == 7: effect = 0.5*hybridMFractal(( x,y,z ),musgrTwo[0].val, musgrTwo[1].val, musgrTwo[2].val, musgrTwo[3].val, musgrTwo[4].val, basis ) + elif Effect_Ctrl[0].val == 8: effect = 0.5*heteroTerrain(( x,y,z ),musgrTwo[0].val, musgrTwo[1].val, musgrTwo[2].val, musgrTwo[3].val, basis )*0.5 + elif Effect_Ctrl[0].val == 9: effect = 0.5*fBm(( x,y,z ),musgrTwo[0].val, musgrTwo[1].val, musgrTwo[2].val, basis )+0.5 + elif Effect_Ctrl[0].val > 9 and Effect_Ctrl[0].val < 31: + effect = Effect_Function((x,y), Effect_Ctrl[0].val-10, Effect_Ctrl[3].val, Effect_Ctrl[4].val, Effect_Ctrl[5].val, Effect_Ctrl[6].val, Effect_Ctrl[7].val ) + elif Effect_Ctrl[0].val == 31: effect = Effect_Ctrl[8].val * random() + elif Effect_Ctrl[0].val == 32: effect = Effect_Ctrl[8].val + elif Effect_Ctrl[0].val == 33: effect = CustomEffect( x,y,z, h ) + effect = HeightScale( effect, iScale[1].val , Offset[1].val, Invert[1].val ) + return effect*2.0 + +###---------------------------------------------------------------------- +# Noise: +##----------------------------------- + +## voronoi_turbulence: +def voroTurbMode((x,y,z), voro, mode ): + if mode == 0: # soft + return voronoi(( x,y,z ),voro[0], voro[1] )[0][0] + if mode == 1: # hard + return ( abs( 0.5-voronoi(( x,y,z ),voro[0], voro[1] )[0][0] ) )+0.5 +def voronoi_turbulence((x,y,z), voro, tur ): + result = voroTurbMode((x,y,z), voro, tur[1] ) + depth = tur[0] + amp = tur[2] + freq = tur[3] + i=0 + for i in xrange( depth ): + i+=1 + result += voroTurbMode( ( x*(freq*i), y*(freq*i), z ), voro, tur[1] )* ( amp*0.5/i ) + return (result*4.0-2.0) + +## DistortedNoise / vlNoise_turbulence: +def vlnTurbMode((x,y,z), vlno, basis, mode ): + if mode == 0: # soft + return vlNoise(( x,y,z ),vlno[0], vlno[1], basis ) + if mode == 1: # hard + return ( abs( -vlNoise(( x,y,z ),vlno[0], vlno[1], basis ) ) ) +def vlNoise_turbulence((x,y,z), vlno, tur, basis ): + result = vlnTurbMode((x,y,z), vlno, basis, tur[1] ) + depth = tur[0] + amp = tur[2] + freq = tur[3] + i=0 + for i in xrange( depth ): + i+=1 + result += vlnTurbMode( ( x*(freq*i), y*(freq*i), z ), vlno, basis, tur[1] ) * ( amp*0.5/i ) + return result*2.0+0.5 + +## marbleNoise: +def marbleNoise( (x,y,z), depth, basis, turb, bias, sharpnes, rescale ): + m = ( x * rescale + y * rescale + z ) * 5 + height = m + turb * turbulence( ( x ,y ,z ), depth, 0, basis, 0.5, 2.0 ) + height = Bias_Types[ bias ]( height ) + if bias != 4: + height = Sharp_Types[ sharpnes ]( height ) + return height*2.0 + +## lava_multiFractal: +def lava_multiFractal( ( x,y,z ),Ha, La, Oc, distort, Basis ): + m = multiFractal( ( x,y,z ), Ha, La, Oc, Basis) + d = m * distort + m2 = 0.5 * multiFractal( ( x+d,y+d,d*0.5 ), Ha, La, Oc, Basis) + return (m * m2)**0.5 + +## slopey_noise: +def slopey_noise((x,y,z), H, lacunarity, octaves, distort, basis ): + x=x*2 + y=y*2 + turb = fBm((x,y,z), H, lacunarity, octaves, 2 ) * 0.5 + map = 0.5 + noise( ( x+turb, y+turb, z ), basis ) + result = map + turb * distort + return result + +## duo_multiFractal: +def double_multiFractal((x,y,z), H, lacunarity, octaves, offset, gain, basis ): + n1 = multiFractal( (x*1.5+1,y*1.5+1,z), 1.0, 1.0, 1.0, basis[0] ) * offset + n2 = multiFractal( (x-1,y-1,z), H, lacunarity, octaves, basis[1] ) * gain + result = ( n1*n1 + n2*n2 )*0.5 + return result + +## distorted_heteroTerrain: +def distorted_heteroTerrain((x,y,z), H, lacunarity, octaves, offset, distort, basis ): + h1 = ( heteroTerrain((x,y,z), 1.0, 2.0, 1.0, 1.0, basis[0] ) * 0.5 ) + h2 = ( heteroTerrain(( x, y, h1*distort ), H, lacunarity, octaves, offset, basis[1] ) * 0.25 ) + result = ( h1*h1 + h2*h2 ) + return result + +## SlickRock: +def SlickRock((x,y,z), H, lacunarity, octaves, offset, gain, basis ): + n = multiFractal( (x,y,z), 1.0, 2.0, 1.0, basis[0] ) + r = ridgedMFractal((x,y,n*0.5), H, lacunarity, octaves, offset, gain, basis[1] )*0.5 + return n+(n*r) + +## terra_turbulence: +def terra_turbulence((x,y,z), depth, hard, basis, amp, freq ): + t2 = turbulence( ( x, y, z ), depth, hard , basis, amp, freq ) + return (t2*t2*t2)+0.5 + +## rocky_fBm: +def rocky_fBm((x,y,z), H, lacunarity, octaves, basis ): + turb = fBm((x,y,z), H, lacunarity, octaves, 2 ) * 0.25 + coords = ( x+turb, y+turb, z ) + map = noise( coords, 7 ) + result = map + fBm( coords, H, lacunarity, octaves, basis ) + 1.0 + return result + +## Shattered_hTerrain: +def Shattered_hTerrain((x,y,z), H, lacunarity, octaves, offset, distort, basis ): + d = ( turbulence( ( x, y, z ), 6, 0, 0, 0.5, 2.0 ) * 0.5 + 0.5 )*distort*0.25 + t0 = ( turbulence( ( x+d, y+d, z ), 0, 0, 7, 0.5, 2.0 ) + 0.5 ) + t2 = ( heteroTerrain(( x*2, y*2, t0*0.5 ), H, lacunarity, octaves, offset, basis ) ) + return (( t0*t2 )+t2*0.5)*0.75 + +## vlhTerrain +def vlhTerrain((x,y,z), H, lacunarity, octaves, offset, basis, vlbasis, distort ): + ht = heteroTerrain(( x, y, z ), H, lacunarity, octaves, offset, basis )*0.5 + vl = ht * vlNoise((x,y,z), distort, basis, vlbasis )*0.5+0.5 + return vl * ht + +####---------------------------------------. +### StatsByAlt, double terrain basis mode: +def TerrainBasisMode((x,y,z), basis, mode ): + if mode == 0: # noise + return noise((x,y,z),basis) + if mode == 1: # noise ridged + return ( 1.0-abs( noise((x,y,z),basis) ) )-0.5 + if mode == 2: # vlNoise + return vlNoise((x,y,z), 1.0, 0, basis ) + else: # vlNoise ridged + return ( 1.0-abs( vlNoise((x,y,z), 1.0, 0, basis ) ) )-0.5 + +#### StatsByAlt terrain: +def StatsByAltTerrain((x,y,z), exp, lacu, octs, offset, amp, basis, mode ): + result = 0.5 * (offset + TerrainBasisMode((x,y,z), basis, mode ) ) + octs = int( octs ) + i = 0 + for i in xrange( 1, octs ): + i += 1 + result += result * amp * 0.5 * (offset + TerrainBasisMode((x,y,z), basis, mode ) ) + x *= lacu + y *= lacu + amp /= ( exp * 0.5 ) * i + return result + +##### double terrain: +def doubleTerrain((x,y,z), exp, lacu, octs, offset, threshold, basis, mode ): + result = amp = freq = 1.0 + #octs = int( octs ) + offset*=0.5 + i = 1 + signal = result = 0.5 * (offset + TerrainBasisMode((x,y,z), basis, mode ) ) + for i in xrange( 1, octs ): + i += 1 + x = x * lacu + y = y * lacu + freq *= lacu + amp = pow( freq, -exp ) + amp *= i + weight = signal / threshold + if weight > 1.0: weight = 1.0 + if weight < 0.0: weigth = 0.0 + signal = weight * 0.5 * ( offset + TerrainBasisMode((x,y,z), basis, mode ) ) + result += amp * signal + return result * 2.0 + +##------------------------------------------------------------ +# Noise Functions: +def Noise_Function(x,y,z): + global Basis, NType, musgr, vlnoi, voron, turbOne, marbleOne, tBasismod + global vlBasis, Distort, VFunc, VExp, VDep + global iScale, Offset, Invert, NSize, Lx, Ly, Sx, Sy + + x,y,z = Trans((x,y,z),( NSize[0].val, Sx[0].val, Sy[0].val, 0 ),( Lx[0].val, Ly[0].val, 0 ) ) + basis = Basis[0].val + if basis == 9: basis = 14 + vbasis = vlnoi[1].val + if vbasis == 9: vbasis = 14 + if NType.val == 0: z = multiFractal(( x,y,z ),musgr[0].val, musgr[1].val, musgr[2].val, basis ) + elif NType.val == 1: z = ridgedMFractal(( x,y,z ),musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, musgr[4].val, basis ) + elif NType.val == 2: z = hybridMFractal(( x,y,z ),musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, musgr[4].val, basis ) + elif NType.val == 3: z = heteroTerrain(( x,y,z ),musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, basis )*0.5 + elif NType.val == 4: z = fBm(( x,y,z ),musgr[0].val, musgr[1].val, musgr[2].val, basis )+0.5 + elif NType.val == 5: z = turbulence(( x,y,z ),turbOne[0].val, turbOne[1].val, basis, turbOne[2].val, turbOne[3].val )+0.5 + elif NType.val == 6: z = voronoi_turbulence((x,y,z),(voron[0].val,voron[1].val),(turbOne[0].val,turbOne[1].val,turbOne[2].val,turbOne[3].val) )*0.5+0.5 + elif NType.val == 7: z = vlNoise_turbulence((x,y,z),(vlnoi[0].val,vbasis), (turbOne[0].val,turbOne[1].val,turbOne[2].val,turbOne[3].val), basis )*0.5+0.5 + elif NType.val == 8: z = noise(( x,y,z ),basis )+0.5 + elif NType.val == 9: z = cellNoise(( x,y,z ))+0.5 + elif NType.val == 10: z = marbleNoise(( x,y,z), marbleOne[0].val, basis, marbleOne[2].val, marbleOne[3].val, marbleOne[4].val, marbleOne[5].val ) + elif NType.val == 11: z = lava_multiFractal(( x,y,z ), musgr[0].val, musgr[1].val, musgr[2].val, vlnoi[0].val, basis ) + elif NType.val == 12: z = slopey_noise(( x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, vlnoi[0].val, basis )+0.5 + elif NType.val == 13: z = double_multiFractal(( x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, musgr[4].val, (vbasis,basis) ) + elif NType.val == 14: z = distorted_heteroTerrain((x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, vlnoi[0].val, (vbasis,basis) ) + elif NType.val == 15: z = SlickRock(( x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, musgr[4].val, (vbasis,basis) ) + elif NType.val == 16: z = terra_turbulence(( x,y,z), turbOne[0].val, turbOne[1].val, basis, turbOne[2].val, turbOne[3].val ) + elif NType.val == 17: z = rocky_fBm(( x,y,z ),musgr[0].val, musgr[1].val, musgr[2].val, basis ) + elif NType.val == 18: z = StatsByAltTerrain( (x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, musgr[4].val*0.5, basis, tBasismod.val ) + elif NType.val == 19: z = doubleTerrain( (x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, musgr[5].val, basis, tBasismod.val ) + elif NType.val == 20: z = Shattered_hTerrain((x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, vlnoi[0].val, basis ) + elif NType.val == 21: z = vlhTerrain((x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, basis, vbasis, vlnoi[0].val ) + else: z = 0.0 + return HeightScale( z, iScale[0].val , Offset[0].val, Invert[0].val ) + +###---------------------------------------------------------------------- +##----------------------------------- +# Filter functions: + +##----------------------------------- +# Filter: Clamp height +def Clamp_Max( height, max ): + if ( height > max ): height = max + return height +def Clamp_Min( height, min ): + if ( height < min ): height = min + return height + +##----------------------------------- +# Filters: terrace / posterise / peaked / bias: +def Def_Filter((x,y,z), input, numb, type ): + if type == 0: + s = ( sin( input*numb*phi ) * ( 0.1/numb*phi ) ) + return ( input * (1.0-0.5) + s*0.5 ) * 2.0 + elif type == 1: + s = -abs( sin( input*(numb*0.5)*phi ) * ( 0.1/(numb*0.5)*phi ) ) + return ( input * (1.0-0.5) + s*0.5 ) * 2.0 + elif type == 2: + s = abs( sin( input*(numb*0.5)*phi ) * ( 0.1/(numb*0.5)*phi ) ) + return ( input * (1.0-0.5) + s*0.5 ) * 2.0 + elif type == 3: + numb = numb*0.5 + s = ( int( input*numb ) * 1.0/numb ) + return ( input * (1.0-0.5) + s*0.5 ) * 2.0 + elif type == 4: + numb = numb*0.5 + s = ( int( input*numb ) * 1.0/numb ) + return ( s ) * 2.0 + elif type == 5: + s = ( sin( input*(2*numb)*phi ) * ( 0.1/(2*numb)*phi ) ) + l = ( input * (1.0-0.5) + s*0.5 ) * 2.0 + p = ( ( l*numb*0.25 ) * ( l*numb*0.25 ) )**2 + return ( l * (1.0-0.5) + p*0.5 ) * 2.0 + elif type == 6: + return ( input*numb*0.25 )**4 + elif type == 7: + return 2.0-exp( 1.0-(input*numb/3.0) ) + elif type == 8: + return sin_bias( input*numb )*2.0 + elif type == 9: + return cos_bias( input*numb )*2.0 + elif type == 10: + return tri_bias( input*numb )*2.0 + elif type == 11: + return saw_bias( input*numb )*2.0 + elif type == 12: + return Clamp_Max( input, numb ) + else: + return input + +##----------------------------------- +# Filter: Edge falloff +def EdgeFalloff( (x,y,z), height, type ): + global Falloff, iScale, Offset + + x = x / Falloff[1].val + y = y / Falloff[2].val + + if Falloff[3].val != 0: + sealevel = (Min.val-Offset[2].val)*2.0/iScale[2].val + else: + sealevel = 0.0 + + falltypes = ( 0, sqrt(x*x+y*y), sqrt((x*x)**2+(y*y)**2), sqrt((x*x)**10+(y*y)**10), sqrt(y*y), sqrt(x*x), abs(x-y), abs(x+y), ((x*x)**10+(y*y)**10)**0.1, ((x*x)+(y*y)) ) + + dist = falltypes[ type ] + if Falloff[4].val != 0: + dist = 1.0 - dist + radius = 1.0 + height = height - sealevel + if( dist < radius ): + dist = dist / radius + dist = ( (dist) * (dist) * ( 3-2*(dist) ) ) + height = ( height - height * dist ) + sealevel + else: + height = sealevel + + if Falloff[3].val != 0: + height = Clamp_Min( height, sealevel ) + else: + height = Clamp_Min( height, Min.val ) + + return height + +##----------------------------------- +# Filter: Custom height filter: +def CustomFilter( x,y,z, h ): + global CustomFilt + try: + a = eval(CustomFilt[0].val) + b = eval(CustomFilt[1].val) + result = eval(CustomFilt[2].val) + return result + except: + return 0.0 + +#####-------------------------------------------------------------------------------------##### +####-------------------------------------------------------------------------------------#### +### Combine Functions: (get noise, Add effect, filter height and return result) ### +##-------------------------------------------------------------------------------------## + +def Combine_Functions( (i,j),(x,y,z) ): + global Effect_Ctrl, Blend_Effect, Filter_Mode, Def_Filter_Ctrl, Ipo_Filter_Ctrl, Filter_Order + global iScale, Offset, Invert, Min, Max, Falloff + + # get noise height: + height = Noise_Function(x,y,0.0) + + ### Filter On + if Filter_Mode.val !=0: + ### 0= Default Filter Order: Noise>Effect>Filter --------------------- + if Filter_Order.val ==0: + # mix noise with effect: + if Effect_Ctrl[0].val !=0: + height = Mix_Modes( (i,j),(x,y,z), height , Effects( (i,j),(x,y,z),height ), Effect_Ctrl[2].val, Effect_Ctrl[1].val ) + # edge fallof: + if Falloff[0].val !=0: + height = EdgeFalloff( (x,y,z), height, Falloff[0].val ) + #else: pass + + if Filter_Mode.val !=0: + # height Def_Filter (Terrace/peaked/bias): + if Filter_Mode.val ==1: + height = Def_Filter((x,y,z), height, Def_Filter_Ctrl[ 1 ].val, Def_Filter_Ctrl[ 0 ].val ) + + ## 'IPOCurve' height filter: + elif Filter_Mode.val ==2: + try: + height = selectedcurve.evaluate( 1 + ( height*Ipo_Filter_Ctrl[2].val/2 ) )*2.0/Ipo_Filter_Ctrl[3].val + except: + height = height + + ## Custom filter: + elif Filter_Mode.val ==3: + height = CustomFilter( x,y,z, height ) + + ### 1= Changed Filter Order: Noise>Filter>Effect --------------------- + if Filter_Order.val !=0: + # mix noise with effect: + if Effect_Ctrl[0].val !=0: + height = Mix_Modes( (i,j),(x,y,z), height , Effects( (i,j),(x,y,z),height ), Effect_Ctrl[2].val, Effect_Ctrl[1].val ) + # edge fallof: + if Falloff[0].val !=0: + height = EdgeFalloff( (x,y,z), height, Falloff[0].val ) + #else: pass + + ### Filter Off --------------------- + else: + # mix noise with effect: + if Effect_Ctrl[0].val !=0: + height = Mix_Modes( (i,j),(x,y,z), height , Effects( (i,j),(x,y,z),height ), Effect_Ctrl[2].val, Effect_Ctrl[1].val ) + # edge fallof: + if Falloff[0].val !=0: + height = EdgeFalloff( (x,y,z), height, Falloff[0].val ) + + # height scale: + height = HeightScale( height, 0.5*iScale[2].val , Offset[2].val, Invert[2].val ) + + # clamp height min. max.: + if Falloff[0].val !=1: + height = Clamp_Min( height, Min.val ) + height = Clamp_Max( height, Max.val ) + + # return height: + return height + + +#------------------------------------------------------------ +##------------------------------------------------------------ +### Render Noise to a Image('NAME') (you must create one first) +##------------------------------------------------------------ +#------------------------------------------------------------ + +def HeightFieldImage(): + global PreView, previewname + + iname = previewname.val + try: + pic = Image.Get( iname ) + except: + #print iname, ' No Image with this name' + PupMenu( 'No Image with this name' ) + return + res = pic.getMaxXY() + for i in xrange( res[0] ): + x = i - (res[0]) / 2.0 + x = (x*2.0) / (res[0]) + for j in xrange( res[1] ): + y = j - (res[1]) / 2.0 + y = (y*2.0) / (res[1]) + height = PreView[2].val + PreView[1].val * Combine_Functions( (i,j),(x,y,0) ) + if height > 1.0: height = 1.0 + if height < 0.0: height = 0.0 + pic.setPixelF( i, j, ( height,height,height, 1.0 ) ) + + +#------------------------------------------------------------ +##------------------------------------------------------------ +### Mesh +##------------------------------------------------------------ +#------------------------------------------------------------ + +#------------------------------------------------------------ +## Mesh: make new grid +###------------------------------------------------------------ + +def MakeGridMesh( RESOL=32, NAME='GridMesh', CURSORPOS=0, SCENE=None ): + # scene, object, mesh --------------------------------------- + if not SCENE: + SCENE = Blender.Scene.GetCurrent() + SCENE.objects.selected=[] + newme = Blender.Mesh.New( NAME ) + newob = SCENE.objects.new( newme, NAME ) + n = RESOL + # verts --------------------------------------- + v=[] + for i in xrange( n ): + x = i-(n-1)/2.0 + x = x*2.0/(n-1) + for j in xrange( n ): + y = j-(n-1)/2.0 + y = y*2.0/(n-1) + v.append( [ x, y, 0 ] ) + newme.verts.extend(v) + # faces --------------------------------------- + f=[] + for i in xrange( n-1 ): + for j in xrange( n-1 ): + f.append( [ i*n+j,\ + (i+1)*n+j,\ + (i+1)*n+j+1,\ + i*n+j+1 ] ) + + newme.faces.extend(f, smooth=True) + #--------------------------------------- + newme.calcNormals() + #--------------------------------------- + if CURSORPOS !=0: + newob.loc = Window.GetCursorPos() + newob.select(1) + +#------------------------------------------------------------ +## Mesh: Grid vert displace / update terrain +###------------------------------------------------------------ + +def displace( OB, ME, WORLD=0 ): + if WORLD == 1: + wx,wy,wz = OB.getLocation( 'worldspace' ) + elif WORLD ==2: + l = OB.getLocation( 'worldspace' ) + w = Window.GetCursorPos() + wx,wy,wz = l[0]-w[0], l[1]-w[1], l[2]-w[2] + else: + wx,wy,wz = 0,0,0 + + for v in ME.verts: + co = v.co + co[2] = Combine_Functions( (co[0]+wx,co[1]+wy),(co[0]+wx, co[1]+wy, 0.0+wz) ) + ME.update() + ME.calcNormals() + #OB.makeDisplayList() + + +#---------------------------------------------------------------------------------------------------- +##---------------------------------------------------------------------------------------------------- +###---------------------------------------------------------------------------------------------------- +####---------------------------------------------------------------------------------------------------- +###---------------------------------------------------------------------------------------------------- +## Do_it: +#-------------------------------------- + +#-------------------------------------- +def do_it(): + global PreView, actme, actob, WorldSpaceCo + if actme !=[]: + if print_time !=0: + t= sys.time() + Window.WaitCursor(1) + in_editmode = Window.EditMode() + if in_editmode: Window.EditMode(0) + if PreView[0].val != 0: + do_it_preview() + displace( actob[0], actme[0], WorldSpaceCo.val ) + Window.RedrawAll() + else: + displace( actob[0], actme[0], WorldSpaceCo.val ) + Window.RedrawAll() + if in_editmode: Window.EditMode(1) + Window.WaitCursor(0) + if print_time !=0: + print 'Generate Mesh: done in %.6f' % (sys.time()-t) + +#-------------------------------------- +def do_it_random(): + global PreView, actme, actob + if actme !=[]: + if print_time !=0: + t= sys.time() + Window.WaitCursor(1) + in_editmode = Window.EditMode() + if in_editmode: Window.EditMode(0) + randomiseNoise() + if PreView[0].val != 0: + do_it_preview() + displace( actob[0], actme[0], WorldSpaceCo.val ) + Window.RedrawAll() + else: + displace( actob[0], actme[0], WorldSpaceCo.val ) + Window.RedrawAll() + if in_editmode: Window.EditMode(1) + Window.WaitCursor(0) + if print_time !=0: + print 'Generate Mesh: done in %.6f' % (sys.time()-t) + +#-------------------------------------- +def do_it_preview(): + if print_time !=0: + t= sys.time() + HeightFieldImage() + Window.RedrawAll() + if print_time !=0: + print 'Generate Image: done in %.6f' % (sys.time()-t) + +###--------------------------------------------------------- +###--------------------------------------------------------- +## load and save: +#------------------------- + +def callback( filename ): + txtFile.val = filename + Register(drawgui, events, bevents) +def writeln(f,x): + f.write(str(x)) + f.write("\n") +def readint(f): + return int(f.readline()) +def readfloat(f): + return float(f.readline()) +def readstr(f): + s = (f.readline()) + return strip(s) + +#-------------------------------------------------- +# Save settings to .ant file +def SavePreset(FName): + global iScale, Offset, Invert, NSize, Sx, Sy, Lx, Ly + global NType, Basis, musgr, tBasismod, vlnoi, vlnoiTwo, voron, turbOne, turbTwo, marbleOne, marbleTwo, musgrTwo + global CustomFX, effect_image, Effect_Ctrl, Min, Max, Falloff, CustomFilt, Filter_Mode, Def_Filter_Ctrl, Ipo_Filter_Ctrl, Filter_Order + global RandMod, RSeed, rand_H, rand_S, rand_L, rand_I, filemessage, fileinfo + + try: + f = open(FName,'w') + writeln(f,CurVersion) + except: + filemessage = "Unable to save file." + return + + writeln(f,fileinfo) + writeln(f,iScale[0].val) + writeln(f,iScale[1].val) + writeln(f,iScale[2].val) + writeln(f,Offset[0].val) + writeln(f,Offset[1].val) + writeln(f,Offset[2].val) + writeln(f,Invert[0].val) + writeln(f,Invert[1].val) + writeln(f,Invert[2].val) + writeln(f,NSize[0].val) + writeln(f,NSize[1].val) + writeln(f,Sx[0].val) + writeln(f,Sx[1].val) + writeln(f,Sy[0].val) + writeln(f,Sy[1].val) + writeln(f,Lx[0].val) + writeln(f,Lx[1].val) + writeln(f,Ly[0].val) + writeln(f,Ly[1].val) + writeln(f,NType.val) + writeln(f,Basis[0].val) + writeln(f,Basis[1].val) + writeln(f,musgr[0].val) + writeln(f,musgr[1].val) + writeln(f,musgr[2].val) + writeln(f,musgr[3].val) + writeln(f,musgr[4].val) + writeln(f,musgr[5].val) + writeln(f,tBasismod.val) + writeln(f,vlnoi[0].val) + writeln(f,vlnoi[1].val) + writeln(f,vlnoiTwo[0].val) + writeln(f,vlnoiTwo[1].val) + writeln(f,voron[0].val) + writeln(f,voron[1].val) + writeln(f,turbOne[0].val) + writeln(f,turbOne[1].val) + writeln(f,turbOne[2].val) + writeln(f,turbOne[3].val) + writeln(f,turbTwo[0].val) + writeln(f,turbTwo[1].val) + writeln(f,turbTwo[2].val) + writeln(f,turbTwo[3].val) + writeln(f,marbleOne[0].val) + writeln(f,marbleOne[1].val) + writeln(f,marbleOne[2].val) + writeln(f,marbleOne[3].val) + writeln(f,marbleOne[4].val) + writeln(f,marbleOne[5].val) + writeln(f,marbleTwo[0].val) + writeln(f,marbleTwo[1].val) + writeln(f,marbleTwo[2].val) + writeln(f,marbleTwo[3].val) + writeln(f,marbleTwo[4].val) + writeln(f,marbleTwo[5].val) + writeln(f,musgrTwo[0].val) + writeln(f,musgrTwo[1].val) + writeln(f,musgrTwo[2].val) + writeln(f,musgrTwo[3].val) + writeln(f,musgrTwo[4].val) + writeln(f,effect_image) + writeln(f,Effect_Ctrl[0].val) + writeln(f,Effect_Ctrl[1].val) + writeln(f,Effect_Ctrl[2].val) + writeln(f,Effect_Ctrl[3].val) + writeln(f,Effect_Ctrl[4].val) + writeln(f,Effect_Ctrl[5].val) + writeln(f,Effect_Ctrl[6].val) + writeln(f,Effect_Ctrl[7].val) + writeln(f,Effect_Ctrl[8].val) + writeln(f,CustomFX[0].val) + writeln(f,CustomFX[1].val) + writeln(f,CustomFX[2].val) + writeln(f,Min.val) + writeln(f,Max.val) + writeln(f,Falloff[0].val) + writeln(f,Falloff[1].val) + writeln(f,Falloff[2].val) + writeln(f,Falloff[3].val) + writeln(f,Falloff[4].val) + writeln(f,Filter_Mode.val) + writeln(f,Filter_Order.val) + writeln(f,CustomFilt[0].val) + writeln(f,CustomFilt[1].val) + writeln(f,CustomFilt[2].val) + writeln(f,Def_Filter_Ctrl[0].val) + writeln(f,Def_Filter_Ctrl[1].val) + writeln(f,Ipo_Filter_Ctrl[0].val) + writeln(f,Ipo_Filter_Ctrl[1].val) + writeln(f,Ipo_Filter_Ctrl[2].val) + writeln(f,Ipo_Filter_Ctrl[3].val) + writeln(f,RandMod.val) + writeln(f,RSeed.val) + writeln(f,rand_H.val) + writeln(f,rand_I.val) + writeln(f,rand_S.val) + writeln(f,rand_L.val) + filemessage = 'Settings saved to file.' + f.close() + +#-------------------------------------------------- +# load settings from .ant file +def LoadPreset(FName): + global iScale, Offset, Invert, NSize, Sx, Sy, Lx, Ly + global NType, Basis, musgr, tBasismod, vlnoi, vlnoiTwo, voron, turbOne, turbTwo, marbleOne, marbleTwo, musgrTwo + global CustomFX, effect_image, Effect_Ctrl, Min, Max, Falloff, CustomFilt, Filter_Mode, Def_Filter_Ctrl, Ipo_Filter_Ctrl, Filter_Order + global RandMod, RSeed, rand_H, rand_S, rand_L, rand_I, filemessage, fileinfo + + try: + f = open(FName,'r') + FVersion = readstr(f) + except: + filemessage = "Unable to open file." + return + + fileinfo = readstr(f) + iScale[0].val = readfloat(f) + iScale[1].val = readfloat(f) + iScale[2].val = readfloat(f) + Offset[0].val = readfloat(f) + Offset[1].val = readfloat(f) + Offset[2].val = readfloat(f) + Invert[0].val = readint(f) + Invert[1].val = readint(f) + Invert[2].val = readint(f) + NSize[0].val = readfloat(f) + NSize[1].val = readfloat(f) + Sx[0].val = readfloat(f) + Sx[1].val = readfloat(f) + Sy[0].val = readfloat(f) + Sy[1].val = readfloat(f) + Lx[0].val = readfloat(f) + Lx[1].val = readfloat(f) + Ly[0].val = readfloat(f) + Ly[1].val = readfloat(f) + NType.val = readint(f) + Basis[0].val = readint(f) + Basis[1].val = readint(f) + musgr[0].val = readfloat(f) + musgr[1].val = readfloat(f) + musgr[2].val = readint(f) + musgr[3].val = readfloat(f) + musgr[4].val = readfloat(f) + musgr[5].val = readfloat(f) + tBasismod.val = readint(f) + vlnoi[0].val = readfloat(f) + vlnoi[1].val = readint(f) + vlnoiTwo[0].val = readfloat(f) + vlnoiTwo[1].val = readint(f) + voron[0].val = readint(f) + voron[1].val = readfloat(f) + turbOne[0].val = readint(f) + turbOne[1].val = readint(f) + turbOne[2].val = readfloat(f) + turbOne[3].val = readfloat(f) + turbTwo[0].val = readint(f) + turbTwo[1].val = readint(f) + turbTwo[2].val = readfloat(f) + turbTwo[3].val = readfloat(f) + marbleOne[0].val = readint(f) + marbleOne[1].val = readint(f) + marbleOne[2].val = readfloat(f) + marbleOne[3].val = readint(f) + marbleOne[4].val = readint(f) + marbleOne[5].val = readfloat(f) + marbleTwo[0].val = readint(f) + marbleTwo[1].val = readint(f) + marbleTwo[2].val = readfloat(f) + marbleTwo[3].val = readint(f) + marbleTwo[4].val = readint(f) + marbleTwo[5].val = readfloat(f) + musgrTwo[0].val = readfloat(f) + musgrTwo[1].val = readfloat(f) + musgrTwo[2].val = readint(f) + musgrTwo[3].val = readfloat(f) + musgrTwo[4].val = readfloat(f) + effect_image = readstr(f) + Effect_Ctrl[0].val = readint(f) + Effect_Ctrl[1].val = readint(f) + Effect_Ctrl[2].val = readfloat(f) + Effect_Ctrl[3].val = readint(f) + Effect_Ctrl[4].val = readfloat(f) + Effect_Ctrl[5].val = readint(f) + Effect_Ctrl[6].val = readfloat(f) + Effect_Ctrl[7].val = readfloat(f) + Effect_Ctrl[8].val = readfloat(f) + CustomFX[0].val = readstr(f) + CustomFX[1].val = readstr(f) + CustomFX[2].val = readstr(f) + Min.val = readfloat(f) + Max.val = readfloat(f) + Falloff[0].val = readint(f) + Falloff[1].val = readfloat(f) + Falloff[2].val = readfloat(f) + Falloff[3].val = readint(f) + Falloff[4].val = readint(f) + Filter_Mode.val = readint(f) + Filter_Order.val = readint(f) + CustomFilt[0].val = readstr(f) + CustomFilt[1].val = readstr(f) + CustomFilt[2].val = readstr(f) + Def_Filter_Ctrl[0].val = readint(f) + Def_Filter_Ctrl[1].val = readfloat(f) + Ipo_Filter_Ctrl[0].val = readstr(f) + Ipo_Filter_Ctrl[1].val = readint(f) + Ipo_Filter_Ctrl[2].val = readfloat(f) + Ipo_Filter_Ctrl[3].val = readfloat(f) + RandMod.val = readint(f) + RSeed.val = readint(f) + rand_H.val = readint(f) + rand_I.val = readint(f) + rand_S.val = readint(f) + rand_L.val = readint(f) + filemessage = 'Settings loaded from file.' + f.close() + +##--------------------------------------------------------------------------- +# Register: + +Register( drawgui, events, bevents ) +###-------------------------------------------------------------------------- + \ No newline at end of file diff --git a/release/ui/space_sequencer.py b/release/ui/space_sequencer.py new file mode 100644 index 00000000000..b64e7d8e0c4 --- /dev/null +++ b/release/ui/space_sequencer.py @@ -0,0 +1,559 @@ + +import bpy + +def act_strip(context): + try: return context.scene.sequence_editor.active_strip + except: return None + +# Header +class SEQUENCER_HT_header(bpy.types.Header): + __space_type__ = "SEQUENCE_EDITOR" + __idname__ = "SEQUENCE_HT_header" + + def draw(self, context): + + st = context.space_data + layout = self.layout + + layout.template_header() + + if context.area.show_menus: + row = layout.row() + row.itemM("SEQUENCER_MT_view") + + row.itemR(st, "display_mode") + + layout.itemS() + + if st.display_mode == 'SEQUENCER': + row.itemM("SEQUENCER_MT_select") + row.itemM("SEQUENCER_MT_marker") + row.itemM("SEQUENCER_MT_add") + row.itemM("SEQUENCER_MT_strip") + layout.itemS() + row.itemO("SEQUENCER_OT_reload") + else: + row.itemR(st, "display_channel") # text="Chan" + +class SEQUENCER_MT_view(bpy.types.Menu): + __space_type__ = "SEQUENCE_EDITOR" + __label__ = "View (TODO)" + + def draw(self, context): + layout = self.layout + st = context.space_data + + layout.column() + + """ + uiBlock *block= uiBeginBlock(C, ar, "seq_viewmenu", UI_EMBOSSP); + short yco= 0, menuwidth=120; + + if (sseq->mainb == SEQ_DRAW_SEQUENCE) { + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, + "Play Back Animation " + "in all Sequence Areas|Alt A", 0, yco-=20, + menuwidth, 19, NULL, 0.0, 0.0, 1, 1, ""); + } + else { + uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, + "Grease Pencil...", 0, yco-=20, + menuwidth, 19, NULL, 0.0, 0.0, 1, 7, ""); + uiDefMenuSep(block); + + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, + "Play Back Animation " + "in this window|Alt A", 0, yco-=20, + menuwidth, 19, NULL, 0.0, 0.0, 1, 1, ""); + } + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, + "Play Back Animation in all " + "3D Views and Sequence Areas|Alt Shift A", + 0, yco-=20, + menuwidth, 19, NULL, 0.0, 0.0, 1, 2, ""); + + """ + layout.itemS() + layout.itemO("SEQUENCER_OT_view_all") + layout.itemO("SEQUENCER_OT_view_selected") + layout.itemS() + """ + + + /* Lock Time */ + uiDefIconTextBut(block, BUTM, 1, (v2d->flag & V2D_VIEWSYNC_SCREEN_TIME)?ICON_CHECKBOX_HLT:ICON_CHECKBOX_DEHLT, + "Lock Time to Other Windows|", 0, yco-=20, + menuwidth, 19, NULL, 0.0, 0.0, 1, 5, ""); + + /* Draw time or frames.*/ + uiDefMenuSep(block); + """ + + layout.itemR(st, "draw_frames") + + """ + if(!sa->full) uiDefIconTextBut(block, BUTM, B_FULL, ICON_BLANK1, "Maximize Window|Ctrl UpArrow", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0,0, ""); + else uiDefIconTextBut(block, BUTM, B_FULL, ICON_BLANK1, "Tile Window|Ctrl DownArrow", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, ""); + + """ + +class SEQUENCER_MT_select(bpy.types.Menu): + __space_type__ = "SEQUENCE_EDITOR" + __label__ = "Select" + + def draw(self, context): + layout = self.layout + st = context.space_data + + layout.column() + layout.item_enumO("SEQUENCER_OT_select_active_side", "side", 'LEFT', text="Strips to the Left") + layout.item_enumO("SEQUENCER_OT_select_active_side", "side", 'RIGHT', text="Strips to the Right") + layout.itemS() + layout.item_enumO("SEQUENCER_OT_select_handles", "side", 'BOTH', text="Surrounding Handles") + layout.item_enumO("SEQUENCER_OT_select_handles", "side", 'LEFT', text="Left Handle") + layout.item_enumO("SEQUENCER_OT_select_handles", "side", 'RIGHT', text="Right Handle") + layout.itemS() + layout.itemO("SEQUENCER_OT_select_linked") + layout.itemO("SEQUENCER_OT_select_all_toggle") + layout.itemO("SEQUENCER_OT_select_invert") + +class SEQUENCER_MT_marker(bpy.types.Menu): + __space_type__ = "SEQUENCE_EDITOR" + __label__ = "Marker (TODO)" + + def draw(self, context): + layout = self.layout + st = context.space_data + + layout.column() + layout.itemO("SEQUENCER_OT_sound_strip_add", text="Add Marker|Ctrl Alt M") + layout.itemO("SEQUENCER_OT_sound_strip_add", text="Duplicate Marker|Ctrl Shift D") + layout.itemO("SEQUENCER_OT_sound_strip_add", text="Delete Marker|Shift X") + layout.itemS() + layout.itemO("SEQUENCER_OT_sound_strip_add", text="(Re)Name Marker|Ctrl M") + layout.itemO("SEQUENCER_OT_sound_strip_add", text="Grab/Move Marker|Ctrl G") + layout.itemS() + layout.itemO("SEQUENCER_OT_sound_strip_add", text="Transform Markers") # toggle, will be rna - (sseq->flag & SEQ_MARKER_TRANS) + +class SEQUENCER_MT_add(bpy.types.Menu): + __space_type__ = "SEQUENCE_EDITOR" + __label__ = "Add" + + def draw(self, context): + layout = self.layout + st = context.space_data + + layout.column() + layout.itemO("SEQUENCER_OT_scene_strip_add", text="Scene") + layout.itemO("SEQUENCER_OT_movie_strip_add", text="Movie") + layout.item_booleanO("SEQUENCER_OT_movie_strip_add", "sound", True, text="Movie & Sound") # FFMPEG ONLY + layout.itemO("SEQUENCER_OT_image_strip_add", text="Image") + layout.itemO("SEQUENCER_OT_sound_strip_add", text="Sound (Ram)") + layout.item_booleanO("SEQUENCER_OT_sound_strip_add", "hd", True, text="Sound (Streaming)") # FFMPEG ONLY + + layout.itemM("SEQUENCER_MT_add_effect") + + +class SEQUENCER_MT_add_effect(bpy.types.Menu): + __space_type__ = "SEQUENCE_EDITOR" + __label__ = "Effect Strip..." + + def draw(self, context): + layout = self.layout + st = context.space_data + + self.layout.column() + self.layout.item_enumO("SEQUENCER_OT_effect_strip_add", 'type', 'ADD') + self.layout.item_enumO("SEQUENCER_OT_effect_strip_add", 'type', 'SUBTRACT') + self.layout.item_enumO("SEQUENCER_OT_effect_strip_add", 'type', 'ALPHA_OVER') + self.layout.item_enumO("SEQUENCER_OT_effect_strip_add", 'type', 'ALPHA_UNDER') + self.layout.item_enumO("SEQUENCER_OT_effect_strip_add", 'type', 'GAMMA_CROSS') + self.layout.item_enumO("SEQUENCER_OT_effect_strip_add", 'type', 'MULTIPLY') + self.layout.item_enumO("SEQUENCER_OT_effect_strip_add", 'type', 'OVER_DROP') + self.layout.item_enumO("SEQUENCER_OT_effect_strip_add", 'type', 'PLUGIN') + self.layout.item_enumO("SEQUENCER_OT_effect_strip_add", 'type', 'WIPE') + self.layout.item_enumO("SEQUENCER_OT_effect_strip_add", 'type', 'GLOW') + self.layout.item_enumO("SEQUENCER_OT_effect_strip_add", 'type', 'TRANSFORM') + self.layout.item_enumO("SEQUENCER_OT_effect_strip_add", 'type', 'COLOR') + self.layout.item_enumO("SEQUENCER_OT_effect_strip_add", 'type', 'SPEED') + +class SEQUENCER_MT_strip(bpy.types.Menu): + __space_type__ = "SEQUENCE_EDITOR" + __label__ = "Strip" + + def draw(self, context): + layout = self.layout + st = context.space_data + + layout.operator_context = 'INVOKE_REGION_WIN' + + layout.column() + layout.item_enumO("TFM_OT_transform", "mode", 'TRANSLATION', text="Grab/Move") + layout.item_enumO("TFM_OT_transform", "mode", 'TIME_EXTEND', text="Grab/Extend from frame") + # uiItemO(layout, NULL, 0, "SEQUENCER_OT_strip_snap"); // TODO - add this operator + layout.itemS() + + layout.item_enumO("SEQUENCER_OT_cut", "type", 'HARD', text="Cut (hard) at frame") + layout.item_enumO("SEQUENCER_OT_cut", "type", 'SOFT', text="Cut (soft) at frame") + layout.itemO("SEQUENCER_OT_images_separate") + layout.itemS() + + layout.itemO("SEQUENCER_OT_duplicate_add") + layout.itemO("SEQUENCER_OT_delete") + + strip = act_strip(context) + + if strip: + stype = strip.type + + if stype=='EFFECT': + layout.itemS() + layout.itemO("SEQUENCER_OT_effect_change") + layout.itemO("SEQUENCER_OT_effect_reassign_inputs") + elif stype=='IMAGE': + layout.itemS() + layout.itemO("SEQUENCER_OT_image_change") + elif stype=='SCENE': + layout.itemS() + layout.itemO("SEQUENCER_OT_scene_change", text="Change Scene") + elif stype=='MOVIE': + layout.itemS() + layout.itemO("SEQUENCER_OT_movie_change") + + layout.itemS() + + layout.itemO("SEQUENCER_OT_meta_make") + layout.itemO("SEQUENCER_OT_meta_separate") + + #if (ed && (ed->metastack.first || (ed->act_seq && ed->act_seq->type == SEQ_META))) { + # uiItemS(layout); + # uiItemO(layout, NULL, 0, "SEQUENCER_OT_meta_toggle"); + #} + + layout.itemS() + layout.itemO("SEQUENCER_OT_reload") + layout.itemS() + layout.itemO("SEQUENCER_OT_lock") + layout.itemO("SEQUENCER_OT_unlock") + layout.itemO("SEQUENCER_OT_mute") + layout.itemO("SEQUENCER_OT_unmute") + + layout.item_enumO("SEQUENCER_OT_mute", property="type", value='UNSELECTED', text="Mute Deselected Strips") + + layout.itemO("SEQUENCER_OT_snap") + +# Panels +class SequencerButtonsPanel(bpy.types.Panel): + __space_type__ = "SEQUENCE_EDITOR" + __region_type__ = "UI" + + def poll(self, context): + return context.space_data.display_mode == 'SEQUENCER' and act_strip(context) != None + +class SequencerButtonsPanel_Output(bpy.types.Panel): + __space_type__ = "SEQUENCE_EDITOR" + __region_type__ = "UI" + + def poll(self, context): + return context.space_data.display_mode != 'SEQUENCER' + +class SEQUENCER_PT_edit(SequencerButtonsPanel): + __label__ = "Edit Strip" + __idname__ = "SEQUENCER_PT_edit" + + def draw(self, context): + layout = self.layout + + strip = act_strip(context) + + layout.itemR(strip, "name") + + layout.itemR(strip, "type") + + layout.itemR(strip, "blend_mode") + + layout.itemR(strip, "blend_opacity", text="Opacity", slider=True) + + split = layout.split() + + col = split.column() + col.itemR(strip, "mute") + col.itemR(strip, "lock") + col.itemR(strip, "frame_locked") + + col = split.column() + col.itemR(strip, "channel") + col.itemR(strip, "start_frame") + col.itemR(strip, "length") + + split = layout.split() + + col = split.column() + col.itemR(strip, "start_offset") + col.itemR(strip, "start_still") + + col = split.column() + col.itemR(strip, "end_offset") + col.itemR(strip, "end_still") + +class SEQUENCER_PT_effect(SequencerButtonsPanel): + __label__ = "Effect Strip" + __idname__ = "SEQUENCER_PT_effect" + + def poll(self, context): + if context.space_data.display_mode != 'SEQUENCER': + return False + + strip = act_strip(context) + if not strip: + return False + + return strip.type in ('COLOR', 'WIPE', 'GLOW', 'SPEED', 'TRANSFORM') + + def draw(self, context): + layout = self.layout + + strip = act_strip(context) + + if strip.type == 'COLOR': + layout.itemR(strip, "color") + + elif strip.type == 'WIPE': + row = layout.row() + row.itemL(text="Transition Type:") + row.itemL(text="Direction:") + + row = layout.row() + row.itemR(strip, "transition_type", text="") + row.itemR(strip, "direction", text="") + + row = layout.row() + row.itemR(strip, "blur_width") + if strip.transition_type in ('SINGLE', 'DOUBLE'): + row.itemR(strip, "angle") + + elif strip.type == 'GLOW': + flow = layout.column_flow() + flow.itemR(strip, "threshold") + flow.itemR(strip, "clamp") + flow.itemR(strip, "boost_factor") + flow.itemR(strip, "blur_distance") + + row = layout.row() + row.itemR(strip, "quality", slider=True) + row.itemR(strip, "only_boost") + + elif strip.type == 'SPEED': + layout.itemR(strip, "global_speed") + + flow = layout.column_flow() + flow.itemR(strip, "curve_velocity") + flow.itemR(strip, "curve_compress_y") + flow.itemR(strip, "frame_blending") + + elif strip.type == 'TRANSFORM': + row = layout.row() + row.itemL(text="Interpolation:") + row.itemL(text="Translation Unit:") + + row = layout.row() + row.itemR(strip, "interpolation", text="") + row.itemR(strip, "translation_unit", text="") + + split = layout.split() + + col = split.column() + sub = col.column(align=True) + sub.itemL(text="Position X:") + sub.itemR(strip, "translate_start_x", text="Start") + sub.itemR(strip, "translate_end_x", text="End") + + sub = col.column(align=True) + sub.itemL(text="Scale X:") + sub.itemR(strip, "scale_start_x", text="Start") + sub.itemR(strip, "scale_end_x", text="End") + + sub = col.column(align=True) + sub.itemL(text="Rotation:") + sub.itemR(strip, "rotation_start", text="Start") + sub.itemR(strip, "rotation_end", text="End") + + col = split.column() + sub = col.column(align=True) + sub.itemL(text="Position Y:") + sub.itemR(strip, "translate_start_y", text="Start") + sub.itemR(strip, "translate_end_y", text="End") + + sub = col.column(align=True) + sub.itemL(text="Scale Y:") + sub.itemR(strip, "scale_start_y", text="Start") + sub.itemR(strip, "scale_end_y", text="End") + +class SEQUENCER_PT_input(SequencerButtonsPanel): + __label__ = "Strip Input" + __idname__ = "SEQUENCER_PT_input" + + def poll(self, context): + if context.space_data.display_mode != 'SEQUENCER': + return False + + strip = act_strip(context) + if not strip: + return False + + return strip.type in ('MOVIE', 'IMAGE', 'SOUND') + + def draw(self, context): + layout = self.layout + + strip = act_strip(context) + + split = layout.split(percentage=0.3) + sub = split.column() + sub.itemL(text="Directory:") + sub = split.column() + sub.itemR(strip, "directory", text="") + + # Current element for the filename + split = layout.split(percentage=0.3) + sub = split.column() + sub.itemL(text="File Name:") + sub = split.column() + + elem = strip.getStripElem(context.scene.current_frame) + if elem: + sub.itemR(elem, "filename", text="") # strip.elements[0] could be a fallback + + layout.itemR(strip, "use_translation") + if strip.transform: + flow = layout.column_flow() + flow.active = strip.use_translation + flow.itemR(strip.transform, "offset_x") + flow.itemR(strip.transform, "offset_y") + + + layout.itemR(strip, "use_crop") + if strip.crop: + flow = layout.column_flow() + flow.active = strip.use_crop + flow.itemR(strip.crop, "top") + flow.itemR(strip.crop, "left") + flow.itemR(strip.crop, "bottom") + flow.itemR(strip.crop, "right") + + layout.itemR(strip, "animation_start_offset") + layout.itemR(strip, "animation_end_offset") + + +class SEQUENCER_PT_filter(SequencerButtonsPanel): + __label__ = "Filter" + __idname__ = "SEQUENCER_PT_filter" + + def poll(self, context): + if context.space_data.display_mode != 'SEQUENCER': + return False + + strip = act_strip(context) + if not strip: + return False + + return strip.type in ('MOVIE', 'IMAGE', 'SCENE', 'META') + + def draw(self, context): + layout = self.layout + + strip = act_strip(context) + + split = layout.split() + + col = split.column() + col.itemR(strip, "premultiply") + col.itemR(strip, "convert_float") + col.itemR(strip, "de_interlace") + col.itemR(strip, "multiply_colors") + col.itemR(strip, "strobe") + + col = split.column() + col.itemL(text="Flip:") + col.itemR(strip, "flip_x", text="X") + col.itemR(strip, "flip_y", text="Y") + col.itemR(strip, "reverse_frames", text="Backwards") + + layout.itemR(strip, "use_color_balance") + if strip.color_balance: # TODO - need to add this somehow + row = layout.row() + row.active = strip.use_color_balance + col = row.column() + col.itemR(strip.color_balance, "lift") + col.itemR(strip.color_balance, "inverse_lift") + col = row.column() + col.itemR(strip.color_balance, "gamma") + col.itemR(strip.color_balance, "inverse_gamma") + col = row.column() + col.itemR(strip.color_balance, "gain") + col.itemR(strip.color_balance, "inverse_gain") + + +class SEQUENCER_PT_proxy(SequencerButtonsPanel): + __label__ = "Proxy" + __idname__ = "SEQUENCER_PT_proxy" + + def poll(self, context): + if context.space_data.display_mode != 'SEQUENCER': + return False + + strip = act_strip(context) + if not strip: + return False + + return strip.type in ('MOVIE', 'IMAGE', 'SCENE', 'META') + + def draw_header(self, context): + strip = act_strip(context) + + layout = self.layout + + layout.itemR(strip, "use_proxy", text="") + + def draw(self, context): + strip = act_strip(context) + + layout = self.layout + + flow = layout.column_flow() + flow.itemR(strip, "proxy_custom_directory") + if strip.proxy: # TODO - need to add this somehow + flow.itemR(strip.proxy, "directory") + flow.itemR(strip.proxy, "file") + + +class SEQUENCER_PT_view(SequencerButtonsPanel_Output): + __label__ = "View Settings" + __idname__ = "SEQUENCER_PT_view" + + def draw(self, context): + st = context.space_data + + layout = self.layout + + flow = layout.column_flow() + flow.itemR(st, "draw_overexposed") # text="Zebra" + flow.itemR(st, "draw_safe_margin") + + +bpy.types.register(SEQUENCER_HT_header) # header/menu classes +bpy.types.register(SEQUENCER_MT_view) +bpy.types.register(SEQUENCER_MT_select) +bpy.types.register(SEQUENCER_MT_marker) +bpy.types.register(SEQUENCER_MT_add) +bpy.types.register(SEQUENCER_MT_add_effect) +bpy.types.register(SEQUENCER_MT_strip) + +bpy.types.register(SEQUENCER_PT_edit) # sequencer panels +bpy.types.register(SEQUENCER_PT_effect) +bpy.types.register(SEQUENCER_PT_input) +bpy.types.register(SEQUENCER_PT_filter) +bpy.types.register(SEQUENCER_PT_proxy) + +bpy.types.register(SEQUENCER_PT_view) # view panels + diff --git a/source/gameengine/Converter/BL_ModifierDeformer.cpp b/source/gameengine/Converter/BL_ModifierDeformer.cpp new file mode 100644 index 00000000000..eb27820c92f --- /dev/null +++ b/source/gameengine/Converter/BL_ModifierDeformer.cpp @@ -0,0 +1,183 @@ +/** + * $Id: BL_ModifierDeformer.cpp 20741 2009-06-08 20:08:19Z blendix $ + * + * ***** 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 ***** + */ + +#ifdef WIN32 +#pragma warning (disable : 4786) +#endif //WIN32 + +#include "MEM_guardedalloc.h" +#include "BL_ModifierDeformer.h" +#include "GEN_Map.h" +#include "STR_HashedString.h" +#include "RAS_IPolygonMaterial.h" +#include "BL_SkinMeshObject.h" +#include "PHY_IGraphicController.h" + +//#include "BL_ArmatureController.h" +#include "DNA_armature_types.h" +#include "DNA_action_types.h" +#include "DNA_key_types.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_ipo_types.h" +#include "DNA_curve_types.h" +#include "DNA_modifier_types.h" +#include "DNA_scene_types.h" +#include "BKE_armature.h" +#include "BKE_action.h" +#include "BKE_key.h" +#include "BKE_ipo.h" +#include "MT_Point3.h" + +extern "C"{ + #include "BKE_customdata.h" + #include "BKE_DerivedMesh.h" + #include "BKE_lattice.h" + #include "BKE_modifier.h" +} + #include "BKE_utildefines.h" + +#include "BLI_blenlib.h" +#include "BLI_arithb.h" + +#define __NLA_DEFNORMALS +//#undef __NLA_DEFNORMALS + + +BL_ModifierDeformer::~BL_ModifierDeformer() +{ + if (m_dm) { + // deformedOnly is used as a user counter + if (--m_dm->deformedOnly == 0) { + m_dm->needsFree = 1; + m_dm->release(m_dm); + } + } +}; + +RAS_Deformer *BL_ModifierDeformer::GetReplica() +{ + BL_ModifierDeformer *result; + + result = new BL_ModifierDeformer(*this); + result->ProcessReplica(); + return result; +} + +void BL_ModifierDeformer::ProcessReplica() +{ + /* Note! - This is not inherited from PyObjectPlus */ + BL_ShapeDeformer::ProcessReplica(); + if (m_dm) + // by default try to reuse mesh, deformedOnly is used as a user count + m_dm->deformedOnly++; + // this will force an update and if the mesh cannot be reused, a new one will be created + m_lastModifierUpdate = -1; +} + +bool BL_ModifierDeformer::HasCompatibleDeformer(Object *ob) +{ + if (!ob->modifiers.first) + return false; + // soft body cannot use mesh modifiers + if ((ob->gameflag & OB_SOFT_BODY) != 0) + return false; + ModifierData* md; + for (md = (ModifierData*)ob->modifiers.first; md; md = (ModifierData*)md->next) { + if (modifier_dependsOnTime(md)) + continue; + if (!(md->mode & eModifierMode_Realtime)) + continue; + return true; + } + return false; +} + +bool BL_ModifierDeformer::Update(void) +{ + bool bShapeUpdate = BL_ShapeDeformer::Update(); + + if (bShapeUpdate || m_lastModifierUpdate != m_gameobj->GetLastFrame()) { + // static derived mesh are not updated + if (m_dm == NULL || m_bDynamic) { + /* execute the modifiers */ + Object* blendobj = m_gameobj->GetBlendObject(); + /* hack: the modifiers require that the mesh is attached to the object + It may not be the case here because of replace mesh actuator */ + Mesh *oldmesh = (Mesh*)blendobj->data; + blendobj->data = m_bmesh; + /* execute the modifiers */ + DerivedMesh *dm = mesh_create_derived_no_virtual(m_scene, blendobj, m_transverts, CD_MASK_MESH); + /* restore object data */ + blendobj->data = oldmesh; + /* free the current derived mesh and replace, (dm should never be NULL) */ + if (m_dm != NULL) { + // HACK! use deformedOnly as a user counter + if (--m_dm->deformedOnly == 0) { + m_dm->needsFree = 1; + m_dm->release(m_dm); + } + } + m_dm = dm; + // get rid of temporary data + m_dm->needsFree = 0; + m_dm->release(m_dm); + // HACK! use deformedOnly as a user counter + m_dm->deformedOnly = 1; + /* update the graphic controller */ + PHY_IGraphicController *ctrl = m_gameobj->GetGraphicController(); + if (ctrl) { + float min_r[3], max_r[3]; + INIT_MINMAX(min_r, max_r); + m_dm->getMinMax(m_dm, min_r, max_r); + ctrl->setLocalAabb(min_r, max_r); + } + } + m_lastModifierUpdate=m_gameobj->GetLastFrame(); + bShapeUpdate = true; + } + return bShapeUpdate; +} + +bool BL_ModifierDeformer::Apply(RAS_IPolyMaterial *mat) +{ + if (!Update()) + return false; + + // drawing is based on derived mesh, must set it in the mesh slots + int nmat = m_pMeshObject->NumMaterials(); + for (int imat=0; imatGetMeshMaterial(imat); + RAS_MeshSlot **slot = mmat->m_slots[(void*)m_gameobj]; + if(!slot || !*slot) + continue; + (*slot)->m_pDerivedMesh = m_dm; + } + return true; +} diff --git a/source/gameengine/Converter/BL_ModifierDeformer.h b/source/gameengine/Converter/BL_ModifierDeformer.h new file mode 100644 index 00000000000..74de54152eb --- /dev/null +++ b/source/gameengine/Converter/BL_ModifierDeformer.h @@ -0,0 +1,107 @@ +/** + * $Id: BL_ModifierDeformer.h 20741 2009-06-08 20:08:19Z blendix $ + * + * ***** 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 ***** + */ + +#ifndef BL_MODIFIERDEFORMER +#define BL_MODIFIERDEFORMER + +#ifdef WIN32 +#pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning +#endif //WIN32 + +#include "BL_ShapeDeformer.h" +#include "BL_DeformableGameObject.h" +#include + +struct DerivedMesh; +struct Object; + +class BL_ModifierDeformer : public BL_ShapeDeformer +{ +public: + static bool HasCompatibleDeformer(Object *ob); + + + BL_ModifierDeformer(BL_DeformableGameObject *gameobj, + Scene *scene, + Object *bmeshobj, + BL_SkinMeshObject *mesh) + : + BL_ShapeDeformer(gameobj,bmeshobj, mesh), + m_lastModifierUpdate(-1), + m_scene(scene), + m_dm(NULL) + { + m_recalcNormal = false; + }; + + /* this second constructor is needed for making a mesh deformable on the fly. */ + BL_ModifierDeformer(BL_DeformableGameObject *gameobj, + struct Scene *scene, + struct Object *bmeshobj_old, + struct Object *bmeshobj_new, + class BL_SkinMeshObject *mesh, + bool release_object, + BL_ArmatureObject* arma = NULL) + : + BL_ShapeDeformer(gameobj, bmeshobj_old, bmeshobj_new, mesh, release_object, false, arma), + m_lastModifierUpdate(-1), + m_scene(scene), + m_dm(NULL) + { + }; + + virtual void ProcessReplica(); + virtual RAS_Deformer *GetReplica(); + virtual ~BL_ModifierDeformer(); + virtual bool UseVertexArray() + { + return false; + } + + bool Update (void); + bool Apply(RAS_IPolyMaterial *mat); + void ForceUpdate() + { + m_lastModifierUpdate = -1.0; + }; + virtual struct DerivedMesh* GetFinalMesh() + { + return m_dm; + } + + +protected: + double m_lastModifierUpdate; + Scene *m_scene; + DerivedMesh *m_dm; + +}; + +#endif + diff --git a/source/gameengine/Ketsji/KX_PythonSeq.cpp b/source/gameengine/Ketsji/KX_PythonSeq.cpp new file mode 100644 index 00000000000..cc8021fc2e4 --- /dev/null +++ b/source/gameengine/Ketsji/KX_PythonSeq.cpp @@ -0,0 +1,382 @@ +/** + * $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: none of this file. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + * Readonly sequence wrapper for lookups on logic bricks + */ + + +#include "KX_PythonSeq.h" +#include "KX_GameObject.h" +#include "SCA_ISensor.h" +#include "SCA_IController.h" +#include "SCA_IActuator.h" + + +PyObject *KX_PythonSeq_CreatePyObject( PyObject *base, short type ) +{ + KX_PythonSeq *seq = PyObject_NEW( KX_PythonSeq, &KX_PythonSeq_Type); + seq->base = base; + Py_INCREF(base); /* so we can always access to check if its valid */ + seq->type = type; + seq->iter = -1; /* init */ + return (PyObject *)seq; + } + + static void KX_PythonSeq_dealloc( KX_PythonSeq * self ) +{ + Py_DECREF(self->base); + PyObject_DEL( self ); +} + +static Py_ssize_t KX_PythonSeq_len( PyObject * self ) +{ + PyObjectPlus *self_plus= BGE_PROXY_REF(((KX_PythonSeq *)self)->base); + + if(self_plus==NULL) { + PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG); + return -1; + } + + switch(((KX_PythonSeq *)self)->type) { + case KX_PYGENSEQ_CONT_TYPE_SENSORS: + return ((SCA_IController *)self_plus)->GetLinkedSensors().size(); + case KX_PYGENSEQ_CONT_TYPE_ACTUATORS: + return ((SCA_IController *)self_plus)->GetLinkedActuators().size(); + case KX_PYGENSEQ_OB_TYPE_SENSORS: + return ((KX_GameObject *)self_plus)->GetSensors().size(); + case KX_PYGENSEQ_OB_TYPE_CONTROLLERS: + return ((KX_GameObject *)self_plus)->GetControllers().size(); + case KX_PYGENSEQ_OB_TYPE_ACTUATORS: + return ((KX_GameObject *)self_plus)->GetActuators().size(); + default: + /* Should never happen */ + PyErr_SetString(PyExc_SystemError, "invalid type, internal error"); + return -1; + } +} + +static PyObject *KX_PythonSeq_getIndex(PyObject* self, int index) +{ + PyObjectPlus *self_plus= BGE_PROXY_REF(((KX_PythonSeq *)self)->base); + + if(self_plus==NULL) { + PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG); + return NULL; + } + + switch(((KX_PythonSeq *)self)->type) { + case KX_PYGENSEQ_CONT_TYPE_SENSORS: + { + vector& linkedsensors = ((SCA_IController *)self_plus)->GetLinkedSensors(); + if(index<0) index += linkedsensors.size(); + if(index<0 || index>= linkedsensors.size()) { + PyErr_SetString(PyExc_IndexError, "seq[i]: index out of range"); + return NULL; + } + return linkedsensors[index]->GetProxy(); + } + case KX_PYGENSEQ_CONT_TYPE_ACTUATORS: + { + vector& linkedactuators = ((SCA_IController *)self_plus)->GetLinkedActuators(); + if(index<0) index += linkedactuators.size(); + if(index<0 || index>= linkedactuators.size()) { + PyErr_SetString(PyExc_IndexError, "seq[i]: index out of range"); + return NULL; + } + return linkedactuators[index]->GetProxy(); + } + case KX_PYGENSEQ_OB_TYPE_SENSORS: + { + SCA_SensorList& linkedsensors= ((KX_GameObject *)self_plus)->GetSensors(); + if(index<0) index += linkedsensors.size(); + if(index<0 || index>= linkedsensors.size()) { + PyErr_SetString(PyExc_IndexError, "seq[i]: index out of range"); + return NULL; + } + return linkedsensors[index]->GetProxy(); + } + case KX_PYGENSEQ_OB_TYPE_CONTROLLERS: + { + SCA_ControllerList& linkedcontrollers= ((KX_GameObject *)self_plus)->GetControllers(); + if(index<0) index += linkedcontrollers.size(); + if(index<0 || index>= linkedcontrollers.size()) { + PyErr_SetString(PyExc_IndexError, "seq[i]: index out of range"); + return NULL; + } + return linkedcontrollers[index]->GetProxy(); + } + case KX_PYGENSEQ_OB_TYPE_ACTUATORS: + { + SCA_ActuatorList& linkedactuators= ((KX_GameObject *)self_plus)->GetActuators(); + if(index<0) index += linkedactuators.size(); + if(index<0 || index>= linkedactuators.size()) { + PyErr_SetString(PyExc_IndexError, "seq[i]: index out of range"); + return NULL; + } + return linkedactuators[index]->GetProxy(); + } + } + + PyErr_SetString(PyExc_SystemError, "invalid sequence type, this is a bug"); + return NULL; +} + + +static PyObject * KX_PythonSeq_subscript(PyObject * self, PyObject *key) +{ + PyObjectPlus *self_plus= BGE_PROXY_REF(((KX_PythonSeq *)self)->base); + char *name = NULL; + + if(self_plus==NULL) { + PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG); + return NULL; + } + + if (PyInt_Check(key)) { + return KX_PythonSeq_getIndex(self, PyInt_AS_LONG( key )); + } else if ( PyString_Check(key) ) { + name = PyString_AsString( key ); + } else { + PyErr_SetString( PyExc_TypeError, "expected a string or an index" ); + return NULL; + } + + switch(((KX_PythonSeq *)self)->type) { + case KX_PYGENSEQ_CONT_TYPE_SENSORS: + { + vector& linkedsensors = ((SCA_IController *)self_plus)->GetLinkedSensors(); + SCA_ISensor* sensor; + for (unsigned int index=0;indexGetName() == name) + return sensor->GetProxy(); + } + break; + } + case KX_PYGENSEQ_CONT_TYPE_ACTUATORS: + { + vector& linkedactuators = ((SCA_IController *)self_plus)->GetLinkedActuators(); + SCA_IActuator* actuator; + for (unsigned int index=0;indexGetName() == name) + return actuator->GetProxy(); + } + break; + } + case KX_PYGENSEQ_OB_TYPE_SENSORS: + { + SCA_SensorList& linkedsensors= ((KX_GameObject *)self_plus)->GetSensors(); + SCA_ISensor *sensor; + for (unsigned int index=0;indexGetName() == name) + return sensor->GetProxy(); + } + break; + } + case KX_PYGENSEQ_OB_TYPE_CONTROLLERS: + { + SCA_ControllerList& linkedcontrollers= ((KX_GameObject *)self_plus)->GetControllers(); + SCA_IController *controller; + for (unsigned int index=0;indexGetName() == name) + return controller->GetProxy(); + } + break; + } + case KX_PYGENSEQ_OB_TYPE_ACTUATORS: + { + SCA_ActuatorList& linkedactuators= ((KX_GameObject *)self_plus)->GetActuators(); + SCA_IActuator *actuator; + for (unsigned int index=0;indexGetName() == name) + return actuator->GetProxy(); + } + break; + } + } + + PyErr_Format( PyExc_KeyError, "requested item \"%s\" does not exist", name); + return NULL; +} + +static PyMappingMethods KX_PythonSeq_as_mapping = { + KX_PythonSeq_len, /* mp_length */ + KX_PythonSeq_subscript, /* mp_subscript */ + 0, /* mp_ass_subscript */ +}; + + +/* + * Initialize the interator index + */ + +static PyObject *KX_PythonSeq_getIter(KX_PythonSeq *self) +{ + if(BGE_PROXY_REF(self->base)==NULL) { + PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG); + return NULL; + } + + /* create a new iterator if were alredy using this one */ + if (self->iter == -1) { + self->iter = 0; + Py_INCREF(self); + return (PyObject *)self; + } else { + return KX_PythonSeq_CreatePyObject(self->base, self->type); + } + } + + +/* + * Return next KX_PythonSeq iter. + */ + +static PyObject *KX_PythonSeq_nextIter(KX_PythonSeq *self) +{ + PyObject *object = KX_PythonSeq_getIndex((PyObject *)self, self->iter); + + self->iter++; + if( object==NULL ) { + self->iter= -1; /* for reuse */ + PyErr_SetString(PyExc_StopIteration, "iterator at end"); + } + return object; /* can be NULL for end of iterator */ +} + + +static int KX_PythonSeq_compare( KX_PythonSeq * a, KX_PythonSeq * b ) /* TODO - python3.x wants richcmp */ +{ + return ( a->type == b->type && a->base == b->base) ? 0 : -1; +} + +/* + * repr function + * convert to a list and get its string value + */ +static PyObject *KX_PythonSeq_repr( KX_PythonSeq * self ) +{ + PyObject *list = PySequence_List((PyObject *)self); + PyObject *repr = PyObject_Repr(list); + Py_DECREF(list); + return repr; +} + + +/*****************************************************************************/ +/* Python KX_PythonSeq_Type structure definition: */ +/*****************************************************************************/ +PyTypeObject KX_PythonSeq_Type = { +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif + /* For printing, in format "." */ + "KX_PythonSeq", /* char *tp_name; */ + sizeof( KX_PythonSeq ), /* int tp_basicsize; */ + 0, /* tp_itemsize; For allocation */ + + /* Methods to implement standard operations */ + + ( destructor ) KX_PythonSeq_dealloc, /* destructor tp_dealloc; */ + NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + ( cmpfunc ) KX_PythonSeq_compare, /* cmpfunc tp_compare; */ + ( reprfunc ) KX_PythonSeq_repr, /* reprfunc tp_repr; */ + + /* Method suites for standard classes */ + + NULL, /* PyNumberMethods *tp_as_number; */ + NULL, /* PySequenceMethods *tp_as_sequence; */ + &KX_PythonSeq_as_mapping, /* PyMappingMethods *tp_as_mapping; */ + + /* More standard operations (here for binary compatibility) */ + + NULL, /* hashfunc tp_hash; */ + NULL, /* ternaryfunc tp_call; */ + NULL, /* reprfunc tp_str; */ + NULL, /* getattrofunc tp_getattro; */ + NULL, /* setattrofunc tp_setattro; */ + + /* Functions to access object as input/output buffer */ + NULL, /* PyBufferProcs *tp_as_buffer; */ + + /*** Flags to define presence of optional/expanded features ***/ + Py_TPFLAGS_DEFAULT, /* long tp_flags; */ + + NULL, /* char *tp_doc; Documentation string */ + /*** Assigned meaning in release 2.0 ***/ + /* call function for all accessible objects */ + NULL, /* traverseproc tp_traverse; */ + + /* delete references to contained objects */ + NULL, /* inquiry tp_clear; */ + + /*** Assigned meaning in release 2.1 ***/ + /*** rich comparisons ***/ + NULL, /* richcmpfunc tp_richcompare; */ + + /*** weak reference enabler ***/ + 0, /* long tp_weaklistoffset; */ + + /*** Added in release 2.2 ***/ + /* Iterators */ + ( getiterfunc) KX_PythonSeq_getIter, /* getiterfunc tp_iter; */ + ( iternextfunc ) KX_PythonSeq_nextIter, /* iternextfunc tp_iternext; */ + + /*** Attribute descriptor and subclassing stuff ***/ + NULL, /* struct PyMethodDef *tp_methods; */ + NULL, /* struct PyMemberDef *tp_members; */ + NULL, /* struct PyGetSetDef *tp_getset; */ + NULL, /* struct _typeobject *tp_base; */ + NULL, /* PyObject *tp_dict; */ + NULL, /* descrgetfunc tp_descr_get; */ + NULL, /* descrsetfunc tp_descr_set; */ + 0, /* long tp_dictoffset; */ + NULL, /* initproc tp_init; */ + NULL, /* allocfunc tp_alloc; */ + NULL, /* newfunc tp_new; */ + /* Low-level free-memory routine */ + NULL, /* freefunc tp_free; */ + /* For PyObject_IS_GC */ + NULL, /* inquiry tp_is_gc; */ + NULL, /* PyObject *tp_bases; */ + /* method resolution order */ + NULL, /* PyObject *tp_mro; */ + NULL, /* PyObject *tp_cache; */ + NULL, /* PyObject *tp_subclasses; */ + NULL, /* PyObject *tp_weaklist; */ + NULL +}; diff --git a/source/gameengine/Ketsji/KX_PythonSeq.h b/source/gameengine/Ketsji/KX_PythonSeq.h new file mode 100644 index 00000000000..15a016224a9 --- /dev/null +++ b/source/gameengine/Ketsji/KX_PythonSeq.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. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + * Readonly sequence wrapper for lookups on logic bricks + */ + +#ifndef _adr_py_seq_h_ // only process once, +#define _adr_py_seq_h_ // even if multiply included + +#include "PyObjectPlus.h" + +// ------------------------- +enum KX_PYGENSEQ_TYPE { + KX_PYGENSEQ_CONT_TYPE_SENSORS, + KX_PYGENSEQ_CONT_TYPE_ACTUATORS, + KX_PYGENSEQ_OB_TYPE_SENSORS, + KX_PYGENSEQ_OB_TYPE_CONTROLLERS, + KX_PYGENSEQ_OB_TYPE_ACTUATORS +}; + +/* The Main PyType Object defined in Main.c */ +extern PyTypeObject KX_PythonSeq_Type; + +#define BPy_KX_PythonSeq_Check(v) \ + ((v)->ob_type == &KX_PythonSeq_Type) + +typedef struct { + PyObject_VAR_HEAD + PyObject *base; + short type; + short iter; +} KX_PythonSeq; + +PyObject *KX_PythonSeq_CreatePyObject(PyObject *base, short type); + +#endif // _adr_py_seq_h_ diff --git a/source/gameengine/PyDoc/API_intro.py b/source/gameengine/PyDoc/API_intro.py new file mode 100644 index 00000000000..ad37e34fbac --- /dev/null +++ b/source/gameengine/PyDoc/API_intro.py @@ -0,0 +1,103 @@ +# This is not a real module, it's simply an introductory text. + +""" +The Blender Game Engine Python API Reference +============================================ + + See U{release notes} for updates, changes and new functionality in the Game Engine Python API. + + Top Module: + ----------- + + - L{GameLogic} + - L{GameKeys} + - L{GameTypes} + - L{Mathutils} + - L{Geometry} + - L{BGL} + + Undocumented modules: + --------------------- + - VideoTexture + - CValue + - Expression + - PhysicsConstraints + + +Introduction: +============= + + This reference documents the Blender Python API, a growing collection of + Python modules (libraries) that give access to part of the program's internal + data and functions. + + Through scripting Blender can be extended in real-time via + U{Python }, an impressive high level, multi-paradigm, open + source language. Newcomers are recommended to start with the tutorial that + comes with it. + + This opens many interesting possibilities not available with logic bricks. + + Game Engine API Stability: + -------------------------- + + When writing python scripts there are a number of situations you should avoid to prevent crashes or unstable behavior. + While the API tries to prevent problems there are some situations where error checking would be too time consuming. + + Known cases: + - Memory Limits. + + There is nothing stopping you from filling a list or making a string so big that that causes blender to run out of memory, in this case python should rasie a MemoryError, but its likely blender will crash before this point. + + - Accessing any data that has been freed. + + For instance accessing a KX_GameObject after its End Object actuator runs. + This will cause a SystemError, however for L{KX_MeshProxy}, L{KX_VertexProxy} and L{KX_VertexProxy} it will crash the blender game engine. + + See: L{GameTypes.PyObjectPlus.invalid} which many types inherit. + + - Mixing L{KX_GameObject} between scenes. + + For instance tracking/parenting an L{KX_GameObject} object to an object from other scene. + + External Modules: + ----------------- + + Since 2.49 support for importing modules has been added. + + This allows you to import any blender textblock with a .py extension. + + External python scripts may be imported as modules when the script is in the same directory as the blend file. + + The current blend files path is included in the sys.path for loading modules. + All linked libraries will also be included so you can be sure when linking in assets from another blend file the scripts will load too. + + A note to newbie script writers: + -------------------------------- + + Interpreted languages are known to be much slower than compiled code, but for + many applications the difference is negligible or acceptable. Also, with + profiling (or even simple direct timing with L{Blender.sys.time}) to + identify slow areas and well thought optimizations, the speed can be + I{considerably} improved in many cases. Try some of the best BPython scripts + to get an idea of what can be done, you may be surprised. + +@author: The Blender Python Team +@requires: Blender 2.49 or newer. +@version: 2.49 +@see: U{www.blender.org}: documentation and forum +@see: U{blenderartists.org}: user forum +@see: U{projects.blender.org} +@see: U{www.python.org} +@see: U{www.python.org/doc} +@see: U{Blending into Python}: User contributed documentation, featuring a blender/python cookbook with many examples. + +@note: the official version of this reference guide is only updated for each + new Blender release. But you can build the current SVN + version yourself: install epydoc, grab all files in the + source/gameengine/PyDoc/ folder of Blender's SVN and use the + epy_docgen.sh script also found there to generate the html docs. + Naturally you will also need a recent Blender binary to try the new + features. If you prefer not to compile it yourself, there is a testing + builds forum at U{blender.org}. +""" diff --git a/source/gameengine/SceneGraph/SG_DList.h b/source/gameengine/SceneGraph/SG_DList.h new file mode 100644 index 00000000000..eea19a85c7a --- /dev/null +++ b/source/gameengine/SceneGraph/SG_DList.h @@ -0,0 +1,161 @@ +/** + * $Id: SG_DList.h 20741 2009-06-08 20:08:19Z blendix $ + * + * ***** 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 ***** + */ +#ifndef __SG_DLIST +#define __SG_DLIST + +#include + +/** + * Double circular linked list + */ +class SG_DList +{ +protected : + SG_DList* m_flink; + SG_DList* m_blink; + +public: + template class iterator + { + private: + SG_DList& m_head; + T* m_current; + public: + typedef iterator _myT; + iterator(SG_DList& head) : m_head(head), m_current(NULL) {} + ~iterator() {} + + void begin() + { + m_current = (T*)m_head.Peek(); + } + void back() + { + m_current = (T*)m_head.Back(); + } + bool end() + { + return (m_current == (T*)m_head.Self()); + } + bool add_back(T* item) + { + return m_current->AddBack(item); + } + T* operator*() + { + return m_current; + } + _myT& operator++() + { + // no check of NULL! make sure you don't try to increment beyond end + m_current = (T*)m_current->Peek(); + return *this; + } + _myT& operator--() + { + // no check of NULL! make sure you don't try to increment beyond end + m_current = (T*)m_current->Back(); + return *this; + } + }; + + SG_DList() + { + m_flink = m_blink = this; + } + SG_DList(const SG_DList& other) + { + m_flink = m_blink = this; + } + virtual ~SG_DList() + { + Delink(); + } + + inline bool Empty() // Check for empty queue + { + return ( m_flink == this ); + } + bool AddBack( SG_DList *item ) // Add to the back + { + if (!item->Empty()) + return false; + item->m_blink = m_blink; + item->m_flink = this; + m_blink->m_flink = item; + m_blink = item; + return true; + } + bool AddFront( SG_DList *item ) // Add to the back + { + if (!item->Empty()) + return false; + item->m_flink = m_flink; + item->m_blink = this; + m_flink->m_blink = item; + m_flink = item; + return true; + } + SG_DList *Remove() // Remove from the front + { + if (Empty()) + { + return NULL; + } + SG_DList* item = m_flink; + m_flink = item->m_flink; + m_flink->m_blink = this; + item->m_flink = item->m_blink = item; + return item; + } + bool Delink() // Remove from the middle + { + if (Empty()) + return false; + m_blink->m_flink = m_flink; + m_flink->m_blink = m_blink; + m_flink = m_blink = this; + return true; + } + inline SG_DList *Peek() // Look at front without removing + { + return m_flink; + } + inline SG_DList *Back() // Look at front without removing + { + return m_blink; + } + inline SG_DList *Self() + { + return this; + } +}; + +#endif //__SG_DLIST + diff --git a/source/gameengine/SceneGraph/SG_QList.h b/source/gameengine/SceneGraph/SG_QList.h new file mode 100644 index 00000000000..6656f5a45c8 --- /dev/null +++ b/source/gameengine/SceneGraph/SG_QList.h @@ -0,0 +1,157 @@ +/** + * $Id: SG_QList.h 20741 2009-06-08 20:08:19Z blendix $ + * + * ***** 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 ***** + */ +#ifndef __SG_QLIST +#define __SG_QLIST + +#include "SG_DList.h" + +/** + * Double-Double circular linked list + * For storing an object is two lists simultaneously + */ +class SG_QList : public SG_DList +{ +protected : + SG_QList* m_fqlink; + SG_QList* m_bqlink; + +public: + template class iterator + { + private: + SG_QList& m_head; + T* m_current; + public: + typedef iterator _myT; + iterator(SG_QList& head, SG_QList* current=NULL) : m_head(head) { m_current = (T*)current; } + ~iterator() {} + + void begin() + { + m_current = (T*)m_head.QPeek(); + } + void back() + { + m_current = (T*)m_head.QBack(); + } + bool end() + { + return (m_current == (T*)m_head.Self()); + } + bool add_back(T* item) + { + return m_current->QAddBack(item); + } + T* operator*() + { + return m_current; + } + _myT& operator++() + { + m_current = (T*)m_current->QPeek(); + return *this; + } + _myT& operator--() + { + // no check on NULL! make sure you don't try to increment beyond end + m_current = (T*)m_current->QBack(); + return *this; + } + }; + + SG_QList() : SG_DList() + { + m_fqlink = m_bqlink = this; + } + SG_QList(const SG_QList& other) : SG_DList() + { + m_fqlink = m_bqlink = this; + } + virtual ~SG_QList() + { + QDelink(); + } + + inline bool QEmpty() // Check for empty queue + { + return ( m_fqlink == this ); + } + bool QAddBack( SG_QList *item ) // Add to the back + { + if (!item->QEmpty()) + return false; + item->m_bqlink = m_bqlink; + item->m_fqlink = this; + m_bqlink->m_fqlink = item; + m_bqlink = item; + return true; + } + bool QAddFront( SG_QList *item ) // Add to the back + { + if (!item->Empty()) + return false; + item->m_fqlink = m_fqlink; + item->m_bqlink = this; + m_fqlink->m_bqlink = item; + m_fqlink = item; + return true; + } + SG_QList *QRemove() // Remove from the front + { + if (QEmpty()) + { + return NULL; + } + SG_QList* item = m_fqlink; + m_fqlink = item->m_fqlink; + m_fqlink->m_bqlink = this; + item->m_fqlink = item->m_bqlink = item; + return item; + } + bool QDelink() // Remove from the middle + { + if (QEmpty()) + return false; + m_bqlink->m_fqlink = m_fqlink; + m_fqlink->m_bqlink = m_bqlink; + m_fqlink = m_bqlink = this; + return true; + } + inline SG_QList *QPeek() // Look at front without removing + { + return m_fqlink; + } + inline SG_QList *QBack() // Look at front without removing + { + return m_bqlink; + } +}; + +#endif //__SG_QLIST + From b1a106dd49a8653977cdfd722b1d30abf827fa28 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 2 Jul 2009 03:32:57 +0000 Subject: [PATCH 075/114] NLA SoC: Merge from 2.5 21210 to 21300 Note to self: the next merge will be messy again, since 2 commits occurred this one was complete --- CMakeLists.txt | 4 +- intern/string/intern/STR_String.cpp | 6 +- .../blender/BPY_python/BPY_python.vcproj | 8 +- projectfiles_vc9/blender/blender.vcproj | 12 +- .../blender/blenkernel/BKE_blenkernel.vcproj | 12 +- .../blender/blenlib/BLI_blenlib.vcproj | 2 +- .../blender/editors/ED_editors.vcproj | 12 +- .../blender/makesrna/RNA_makesrna.vcproj | 2 +- .../blender/makesrna/RNA_rna.vcproj | 2 +- projectfiles_vc9/blender/nodes/nodes.vcproj | 8 +- .../blenderhook/KX_blenderhook.vcproj | 4 +- .../gameengine/converter/KX_converter.vcproj | 12 +- .../expression/EXP_expressions.vcproj | 12 +- .../gameengine/gamelogic/SCA_GameLogic.vcproj | 12 +- .../gameplayer/axctl/GP_axctl.vcproj | 4 +- .../gameplayer/common/GP_common.vcproj | 8 +- .../gameplayer/ghost/GP_ghost.vcproj | 4 +- .../gameengine/ketsji/KX_ketsji.vcproj | 12 +- .../ketsji/network/KX_network.vcproj | 12 +- .../PHY_Physics/PHY_Bullet/PHY_Bullet.vcproj | 12 +- .../rasterizer/RAS_rasterizer.vcproj | 12 +- .../gameengine/videotexture/TEX_Video.vcproj | 4 +- .../kernel/system/SYS_system.vcproj | 4 +- release/ui/buttons_data_mesh.py | 107 ++- release/ui/buttons_data_modifier.py | 2 +- release/ui/buttons_particle.py | 6 +- release/ui/space_buttons.py | 2 +- release/ui/space_filebrowser.py | 65 ++ release/ui/space_image.py | 42 +- release/ui/space_info.py | 119 +++ source/blender/blenkernel/BKE_packedFile.h | 52 +- source/blender/blenkernel/BKE_particle.h | 4 +- source/blender/blenkernel/BKE_report.h | 5 +- .../blender/blenkernel/intern/cdderivedmesh.c | 2 +- source/blender/blenkernel/intern/context.c | 3 + source/blender/blenkernel/intern/displist.c | 36 +- source/blender/blenkernel/intern/font.c | 8 +- source/blender/blenkernel/intern/image.c | 6 +- source/blender/blenkernel/intern/packedFile.c | 227 ++--- source/blender/blenkernel/intern/particle.c | 6 +- source/blender/blenkernel/intern/report.c | 4 +- source/blender/blenlib/BLI_util.h | 1 + source/blender/blenlib/intern/storage.c | 42 +- source/blender/blenlib/intern/util.c | 19 + source/blender/blenloader/intern/readfile.c | 21 +- .../blender/editors/include/ED_fileselect.h | 32 +- source/blender/editors/include/ED_mesh.h | 4 +- source/blender/editors/include/UI_interface.h | 6 +- source/blender/editors/interface/interface.c | 10 +- .../editors/interface/interface_handlers.c | 41 +- .../editors/interface/interface_icons.c | 17 +- .../editors/interface/interface_layout.c | 2 +- .../editors/interface/interface_panel.c | 4 + .../editors/interface/interface_regions.c | 55 +- .../editors/interface/interface_templates.c | 311 +++--- .../editors/interface/interface_utils.c | 2 +- .../editors/interface/interface_widgets.c | 4 +- source/blender/editors/mesh/mesh_intern.h | 9 + source/blender/editors/mesh/mesh_layers.c | 424 +++++++++ source/blender/editors/mesh/mesh_ops.c | 6 + source/blender/editors/object/editkey.c | 144 ++- source/blender/editors/object/object_intern.h | 14 + source/blender/editors/object/object_ops.c | 12 + .../editdeform.c => object/object_vgroup.c} | 274 +++++- source/blender/editors/screen/screen_ops.c | 5 +- source/blender/editors/sculpt_paint/sculpt.c | 144 ++- .../editors/space_buttons/buttons_intern.h | 4 +- .../editors/space_buttons/buttons_ops.c | 20 +- .../editors/space_buttons/space_buttons.c | 5 +- source/blender/editors/space_file/file_draw.c | 128 --- .../blender/editors/space_file/file_intern.h | 12 +- source/blender/editors/space_file/file_ops.c | 220 +++-- .../blender/editors/space_file/file_panels.c | 165 ++++ source/blender/editors/space_file/filelist.c | 8 +- source/blender/editors/space_file/filelist.h | 1 - source/blender/editors/space_file/filesel.c | 2 +- source/blender/editors/space_file/fsmenu.c | 39 +- source/blender/editors/space_file/fsmenu.h | 13 +- .../blender/editors/space_file/space_file.c | 126 +-- .../editors/space_image/image_buttons.c | 4 +- .../blender/editors/space_image/image_ops.c | 97 +- .../blender/editors/space_info/info_header.c | 507 ---------- .../blender/editors/space_info/info_intern.h | 7 + source/blender/editors/space_info/info_ops.c | 397 ++++++++ .../blender/editors/space_info/space_info.c | 28 +- .../editors/space_view3d/view3d_header.c | 1 + .../editors/space_view3d/view3d_toolbar.c | 2 +- .../editors/space_view3d/view3d_view.c | 3 + source/blender/makesdna/DNA_brush_types.h | 1 + source/blender/makesdna/DNA_scene_types.h | 6 +- source/blender/makesdna/DNA_screen_types.h | 4 + source/blender/makesdna/DNA_space_types.h | 48 +- .../makesdna/DNA_windowmanager_types.h | 3 +- source/blender/makesrna/RNA_access.h | 10 + source/blender/makesrna/RNA_types.h | 19 +- source/blender/makesrna/intern/makesrna.c | 89 +- source/blender/makesrna/intern/rna_access.c | 377 +++++++- source/blender/makesrna/intern/rna_brush.c | 4 + .../blender/makesrna/intern/rna_constraint.c | 4 +- source/blender/makesrna/intern/rna_context.c | 20 +- source/blender/makesrna/intern/rna_define.c | 13 +- source/blender/makesrna/intern/rna_image.c | 19 + source/blender/makesrna/intern/rna_internal.h | 1 + .../makesrna/intern/rna_internal_types.h | 4 + source/blender/makesrna/intern/rna_mesh.c | 235 +++-- source/blender/makesrna/intern/rna_mesh_api.c | 221 ++++- source/blender/makesrna/intern/rna_object.c | 103 +- source/blender/makesrna/intern/rna_rna.c | 16 +- source/blender/makesrna/intern/rna_scene.c | 5 + source/blender/makesrna/intern/rna_screen.c | 28 + source/blender/makesrna/intern/rna_space.c | 123 ++- source/blender/makesrna/intern/rna_ui.c | 16 +- source/blender/makesrna/intern/rna_ui_api.c | 7 + source/blender/makesrna/intern/rna_wm.c | 46 + source/blender/python/generic/BGL.c | 9 +- source/blender/python/generic/Geometry.c | 12 +- source/blender/python/generic/Mathutils.c | 36 +- source/blender/python/generic/euler.c | 84 +- source/blender/python/generic/euler.h | 5 +- source/blender/python/generic/matrix.c | 216 +++-- source/blender/python/generic/matrix.h | 5 +- source/blender/python/generic/quat.c | 110 ++- source/blender/python/generic/quat.h | 5 +- source/blender/python/generic/vector.c | 888 ++++++++++-------- source/blender/python/generic/vector.h | 5 +- .../blender/python/intern/bpy_operator_wrap.c | 3 +- source/blender/python/intern/bpy_rna.c | 550 +++++++++-- source/blender/windowmanager/WM_api.h | 2 +- source/blender/windowmanager/WM_types.h | 5 + .../windowmanager/intern/wm_event_system.c | 14 +- .../blender/windowmanager/intern/wm_files.c | 2 +- .../blender/windowmanager/intern/wm_keymap.c | 2 +- .../windowmanager/intern/wm_operators.c | 2 +- source/creator/CMakeLists.txt | 5 +- source/gameengine/BlenderRoutines/Makefile | 1 + .../Converter/BL_ActionActuator.cpp | 43 +- .../gameengine/Converter/BL_ActionActuator.h | 9 +- .../Converter/BL_ShapeActionActuator.cpp | 40 +- .../Converter/BL_ShapeActionActuator.h | 9 +- source/gameengine/Expressions/BoolValue.cpp | 3 +- source/gameengine/Expressions/IntValue.cpp | 2 +- source/gameengine/Expressions/ListValue.cpp | 59 +- source/gameengine/Expressions/ListValue.h | 4 +- .../gameengine/Expressions/PyObjectPlus.cpp | 371 +++----- source/gameengine/Expressions/PyObjectPlus.h | 95 +- source/gameengine/Expressions/StringValue.h | 2 +- source/gameengine/Expressions/Value.cpp | 124 +-- source/gameengine/Expressions/Value.h | 16 +- .../GameLogic/SCA_2DFilterActuator.cpp | 42 +- .../GameLogic/SCA_2DFilterActuator.h | 13 +- .../GameLogic/SCA_ANDController.cpp | 31 +- .../gameengine/GameLogic/SCA_ANDController.h | 10 +- .../GameLogic/SCA_ActuatorSensor.cpp | 37 +- .../gameengine/GameLogic/SCA_ActuatorSensor.h | 7 +- .../gameengine/GameLogic/SCA_AlwaysSensor.cpp | 31 +- .../gameengine/GameLogic/SCA_AlwaysSensor.h | 12 +- .../gameengine/GameLogic/SCA_DelaySensor.cpp | 40 +- source/gameengine/GameLogic/SCA_DelaySensor.h | 7 +- .../GameLogic/SCA_ExpressionController.cpp | 5 +- .../GameLogic/SCA_ExpressionController.h | 11 +- source/gameengine/GameLogic/SCA_IActuator.cpp | 5 +- source/gameengine/GameLogic/SCA_IActuator.h | 3 +- .../gameengine/GameLogic/SCA_IController.cpp | 47 +- source/gameengine/GameLogic/SCA_IController.h | 6 +- .../gameengine/GameLogic/SCA_ILogicBrick.cpp | 44 +- source/gameengine/GameLogic/SCA_ILogicBrick.h | 6 +- source/gameengine/GameLogic/SCA_IObject.cpp | 81 +- source/gameengine/GameLogic/SCA_IObject.h | 7 +- source/gameengine/GameLogic/SCA_ISensor.cpp | 46 +- source/gameengine/GameLogic/SCA_ISensor.h | 7 +- .../GameLogic/SCA_JoystickSensor.cpp | 73 +- .../gameengine/GameLogic/SCA_JoystickSensor.h | 7 +- .../GameLogic/SCA_KeyboardSensor.cpp | 61 +- .../gameengine/GameLogic/SCA_KeyboardSensor.h | 7 +- .../gameengine/GameLogic/SCA_LogicManager.cpp | 1 + .../gameengine/GameLogic/SCA_MouseSensor.cpp | 47 +- source/gameengine/GameLogic/SCA_MouseSensor.h | 7 +- .../GameLogic/SCA_NANDController.cpp | 31 +- .../gameengine/GameLogic/SCA_NANDController.h | 6 +- .../GameLogic/SCA_NORController.cpp | 31 +- .../gameengine/GameLogic/SCA_NORController.h | 10 +- .../gameengine/GameLogic/SCA_ORController.cpp | 32 +- .../gameengine/GameLogic/SCA_ORController.h | 9 +- .../GameLogic/SCA_PropertyActuator.cpp | 38 +- .../GameLogic/SCA_PropertyActuator.h | 8 +- .../GameLogic/SCA_PropertySensor.cpp | 42 +- .../gameengine/GameLogic/SCA_PropertySensor.h | 7 +- .../GameLogic/SCA_PythonController.cpp | 63 +- .../GameLogic/SCA_PythonController.h | 6 +- .../GameLogic/SCA_RandomActuator.cpp | 48 +- .../gameengine/GameLogic/SCA_RandomActuator.h | 7 +- .../gameengine/GameLogic/SCA_RandomSensor.cpp | 46 +- .../gameengine/GameLogic/SCA_RandomSensor.h | 7 +- .../GameLogic/SCA_XNORController.cpp | 31 +- .../gameengine/GameLogic/SCA_XNORController.h | 5 +- .../GameLogic/SCA_XORController.cpp | 31 +- .../gameengine/GameLogic/SCA_XORController.h | 10 +- source/gameengine/Ketsji/BL_Shader.cpp | 43 +- source/gameengine/Ketsji/BL_Shader.h | 6 +- .../KXNetwork/KX_NetworkMessageActuator.cpp | 37 +- .../KXNetwork/KX_NetworkMessageActuator.h | 7 +- .../KXNetwork/KX_NetworkMessageSensor.cpp | 43 +- .../KXNetwork/KX_NetworkMessageSensor.h | 7 +- .../gameengine/Ketsji/KX_BlenderMaterial.cpp | 43 +- source/gameengine/Ketsji/KX_BlenderMaterial.h | 9 +- source/gameengine/Ketsji/KX_CDActuator.cpp | 47 +- source/gameengine/Ketsji/KX_CDActuator.h | 7 +- source/gameengine/Ketsji/KX_Camera.cpp | 65 +- source/gameengine/Ketsji/KX_Camera.h | 7 +- .../gameengine/Ketsji/KX_CameraActuator.cpp | 39 +- source/gameengine/Ketsji/KX_CameraActuator.h | 8 +- .../Ketsji/KX_ConstraintActuator.cpp | 50 +- .../gameengine/Ketsji/KX_ConstraintActuator.h | 7 +- .../Ketsji/KX_ConstraintWrapper.cpp | 42 +- .../gameengine/Ketsji/KX_ConstraintWrapper.h | 5 +- source/gameengine/Ketsji/KX_GameActuator.cpp | 45 +- source/gameengine/Ketsji/KX_GameActuator.h | 7 +- source/gameengine/Ketsji/KX_GameObject.cpp | 185 +--- source/gameengine/Ketsji/KX_GameObject.h | 17 +- source/gameengine/Ketsji/KX_IpoActuator.cpp | 37 +- source/gameengine/Ketsji/KX_IpoActuator.h | 7 +- source/gameengine/Ketsji/KX_Light.cpp | 56 +- source/gameengine/Ketsji/KX_Light.h | 6 +- source/gameengine/Ketsji/KX_MeshProxy.cpp | 55 +- source/gameengine/Ketsji/KX_MeshProxy.h | 3 - .../gameengine/Ketsji/KX_MouseFocusSensor.cpp | 33 +- .../gameengine/Ketsji/KX_MouseFocusSensor.h | 5 +- source/gameengine/Ketsji/KX_NearSensor.cpp | 46 +- source/gameengine/Ketsji/KX_NearSensor.h | 9 +- .../gameengine/Ketsji/KX_ObjectActuator.cpp | 43 +- source/gameengine/Ketsji/KX_ObjectActuator.h | 7 +- .../gameengine/Ketsji/KX_ParentActuator.cpp | 37 +- source/gameengine/Ketsji/KX_ParentActuator.h | 7 +- .../Ketsji/KX_PhysicsObjectWrapper.cpp | 49 +- .../Ketsji/KX_PhysicsObjectWrapper.h | 6 +- source/gameengine/Ketsji/KX_PolyProxy.cpp | 61 +- source/gameengine/Ketsji/KX_PolyProxy.h | 2 - .../gameengine/Ketsji/KX_PolygonMaterial.cpp | 44 +- source/gameengine/Ketsji/KX_PolygonMaterial.h | 7 +- .../Ketsji/KX_PyConstraintBinding.cpp | 2 +- source/gameengine/Ketsji/KX_PyMath.cpp | 12 +- source/gameengine/Ketsji/KX_PyMath.h | 14 +- source/gameengine/Ketsji/KX_PythonInit.cpp | 38 +- .../gameengine/Ketsji/KX_PythonInitTypes.cpp | 225 +++-- source/gameengine/Ketsji/KX_PythonSeq.cpp | 137 ++- source/gameengine/Ketsji/KX_RadarSensor.cpp | 40 +- source/gameengine/Ketsji/KX_RadarSensor.h | 7 +- source/gameengine/Ketsji/KX_RaySensor.cpp | 39 +- source/gameengine/Ketsji/KX_RaySensor.h | 8 +- .../Ketsji/KX_SCA_AddObjectActuator.cpp | 45 +- .../Ketsji/KX_SCA_AddObjectActuator.h | 7 +- .../Ketsji/KX_SCA_DynamicActuator.cpp | 45 +- .../Ketsji/KX_SCA_DynamicActuator.h | 8 +- .../Ketsji/KX_SCA_EndObjectActuator.cpp | 35 +- .../Ketsji/KX_SCA_EndObjectActuator.h | 6 +- .../Ketsji/KX_SCA_ReplaceMeshActuator.cpp | 45 +- .../Ketsji/KX_SCA_ReplaceMeshActuator.h | 9 +- source/gameengine/Ketsji/KX_Scene.cpp | 88 +- source/gameengine/Ketsji/KX_Scene.h | 10 +- source/gameengine/Ketsji/KX_SceneActuator.cpp | 50 +- source/gameengine/Ketsji/KX_SceneActuator.h | 7 +- source/gameengine/Ketsji/KX_SoundActuator.cpp | 53 +- source/gameengine/Ketsji/KX_SoundActuator.h | 7 +- source/gameengine/Ketsji/KX_StateActuator.cpp | 41 +- source/gameengine/Ketsji/KX_StateActuator.h | 9 +- source/gameengine/Ketsji/KX_TouchSensor.cpp | 44 +- source/gameengine/Ketsji/KX_TouchSensor.h | 7 +- .../gameengine/Ketsji/KX_TrackToActuator.cpp | 51 +- source/gameengine/Ketsji/KX_TrackToActuator.h | 5 +- .../gameengine/Ketsji/KX_VehicleWrapper.cpp | 44 +- source/gameengine/Ketsji/KX_VehicleWrapper.h | 5 +- source/gameengine/Ketsji/KX_VertexProxy.cpp | 96 +- source/gameengine/Ketsji/KX_VertexProxy.h | 3 - .../Ketsji/KX_VisibilityActuator.cpp | 43 +- .../gameengine/Ketsji/KX_VisibilityActuator.h | 8 +- .../VideoTexture/FilterBlueScreen.cpp | 20 +- .../gameengine/VideoTexture/FilterColor.cpp | 8 +- .../gameengine/VideoTexture/FilterNormal.cpp | 4 +- .../gameengine/VideoTexture/ImageRender.cpp | 16 +- .../gameengine/VideoTexture/ImageViewport.cpp | 16 +- source/gameengine/VideoTexture/VideoBase.cpp | 4 +- .../gameengine/VideoTexture/VideoFFmpeg.cpp | 4 +- .../gameengine/VideoTexture/blendVideoTex.cpp | 2 +- 283 files changed, 6697 insertions(+), 5513 deletions(-) create mode 100644 release/ui/space_filebrowser.py create mode 100644 release/ui/space_info.py create mode 100644 source/blender/editors/mesh/mesh_layers.c rename source/blender/editors/{mesh/editdeform.c => object/object_vgroup.c} (80%) create mode 100644 source/blender/editors/space_file/file_panels.c delete mode 100644 source/blender/editors/space_info/info_header.c create mode 100644 source/blender/editors/space_info/info_ops.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 99f1c10027b..714ec4095af 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -193,10 +193,10 @@ IF(WIN32) ENDIF(CMAKE_CL_64) SET(PYTHON ${LIBDIR}/python) - SET(PYTHON_VERSION 2.5) + SET(PYTHON_VERSION 2.6) SET(PYTHON_INC "${PYTHON}/include/python${PYTHON_VERSION}") SET(PYTHON_BINARY python) - SET(PYTHON_LIB python25) + SET(PYTHON_LIB python26) SET(PYTHON_LIBPATH ${PYTHON}/lib) IF(CMAKE_CL_64) diff --git a/intern/string/intern/STR_String.cpp b/intern/string/intern/STR_String.cpp index dcc52e2a3e7..646b1a853dc 100644 --- a/intern/string/intern/STR_String.cpp +++ b/intern/string/intern/STR_String.cpp @@ -559,7 +559,8 @@ STR_String& STR_String::TrimLeft() { int skip; assertd(pData != NULL); - for (skip=0; isSpace(pData[skip]); skip++, Len--); + for (skip=0; isSpace(pData[skip]); skip++, Len--) + {}; memmove(pData, pData+skip, Len+1); return *this; } @@ -598,7 +599,8 @@ STR_String& STR_String::TrimLeft(char *set) { int skip; assertd(pData != NULL); - for (skip=0; Len && strchr(set, pData[skip]); skip++, Len--); + for (skip=0; Len && strchr(set, pData[skip]); skip++, Len--) + {}; memmove(pData, pData+skip, Len+1); return *this; } diff --git a/projectfiles_vc9/blender/BPY_python/BPY_python.vcproj b/projectfiles_vc9/blender/BPY_python/BPY_python.vcproj index 341275a5b5a..f6a740ee5b0 100644 --- a/projectfiles_vc9/blender/BPY_python/BPY_python.vcproj +++ b/projectfiles_vc9/blender/BPY_python/BPY_python.vcproj @@ -43,7 +43,7 @@ diff --git a/projectfiles_vc9/blender/blenkernel/BKE_blenkernel.vcproj b/projectfiles_vc9/blender/blenkernel/BKE_blenkernel.vcproj index cc464b9101a..63b2b21971f 100644 --- a/projectfiles_vc9/blender/blenkernel/BKE_blenkernel.vcproj +++ b/projectfiles_vc9/blender/blenkernel/BKE_blenkernel.vcproj @@ -43,7 +43,7 @@ + + @@ -795,11 +799,11 @@ Name="space_info" > 1: + col.itemO("OBJECT_OT_vertex_group_copy_to_linked", icon="ICON_BLANK1", text="") + + if context.edit_object: + row = layout.row(align=True) + + row.itemO("OBJECT_OT_vertex_group_assign", text="Assign") + row.itemO("OBJECT_OT_vertex_group_remove_from", text="Remove") + row.itemO("OBJECT_OT_vertex_group_select", text="Select") + row.itemO("OBJECT_OT_vertex_group_deselect", text="Deselect") + + layout.itemR(context.tool_settings, "vertex_group_weight", text="Weight") + +class DATA_PT_shape_keys(DataButtonsPanel): + __idname__ = "DATA_PT_shape_keys" + __label__ = "Shape Keys" + + def poll(self, context): + return (context.object and context.object.type in ('MESH', 'LATTICE')) + + def draw(self, context): + layout = self.layout + ob = context.object + + row = layout.row() + + key = ob.data.shape_keys + + row.template_list(key, "keys", ob, "active_shape_key_index") + + col = row.column(align=True) + col.itemO("OBJECT_OT_shape_key_add", icon="ICON_ZOOMIN", text="") + col.itemO("OBJECT_OT_shape_key_remove", icon="ICON_ZOOMOUT", text="") + + if context.edit_object: + layout.enabled = False + +class DATA_PT_uv_texture(DataButtonsPanel): + __idname__ = "DATA_PT_uv_texture" + __label__ = "UV Texture" + + def draw(self, context): + layout = self.layout + me = context.mesh + + row = layout.row() + + row.template_list(me, "uv_textures", me, "active_uv_texture_index") + + col = row.column(align=True) + col.itemO("MESH_OT_uv_texture_add", icon="ICON_ZOOMIN", text="") + col.itemO("MESH_OT_uv_texture_remove", icon="ICON_ZOOMOUT", text="") + +class DATA_PT_vertex_colors(DataButtonsPanel): + __idname__ = "DATA_PT_vertex_colors" + __label__ = "Vertex Colors" + + def draw(self, context): + layout = self.layout + me = context.mesh + + row = layout.row() + + row.template_list(me, "vertex_colors", me, "active_vertex_color_index") + + col = row.column(align=True) + col.itemO("MESH_OT_vertex_color_add", icon="ICON_ZOOMIN", text="") + col.itemO("MESH_OT_vertex_color_remove", icon="ICON_ZOOMOUT", text="") bpy.types.register(DATA_PT_mesh) bpy.types.register(DATA_PT_materials) +bpy.types.register(DATA_PT_vertex_groups) +bpy.types.register(DATA_PT_shape_keys) +bpy.types.register(DATA_PT_uv_texture) +bpy.types.register(DATA_PT_vertex_colors) diff --git a/release/ui/buttons_data_modifier.py b/release/ui/buttons_data_modifier.py index 9d24cd2d534..af0a8582174 100644 --- a/release/ui/buttons_data_modifier.py +++ b/release/ui/buttons_data_modifier.py @@ -350,7 +350,7 @@ class DATA_PT_modifiers(DataButtonsPanel): sub.itemR(md, "factor") sub.itemR(md, "repeat") - layout.template_pointer(md, "vertex_group", ob, "vertex_groups") + layout.item_pointerR(md, "vertex_group", ob, "vertex_groups") def softbody(self, layout, ob, md): layout.itemL(text="See Softbody panel.") diff --git a/release/ui/buttons_particle.py b/release/ui/buttons_particle.py index e51df6ef7fd..49ceaf6aae1 100644 --- a/release/ui/buttons_particle.py +++ b/release/ui/buttons_particle.py @@ -33,11 +33,11 @@ class PARTICLE_PT_particles(ParticleButtonsPanel): if ob: row = layout.row() - row.template_list(ob, "particle_systems", "active_particle_system_index") + row.template_list(ob, "particle_systems", ob, "active_particle_system_index") col = row.column(align=True) - col.itemO("OBJECT_OT_particle_system_slot_add", icon="ICON_ZOOMIN", text="") - col.itemO("OBJECT_OT_particle_system_slot_remove", icon="ICON_ZOOMOUT", text="") + col.itemO("OBJECT_OT_particle_system_add", icon="ICON_ZOOMIN", text="") + col.itemO("OBJECT_OT_particle_system_remove", icon="ICON_ZOOMOUT", text="") if psys: split = layout.split(percentage=0.65) diff --git a/release/ui/space_buttons.py b/release/ui/space_buttons.py index a669690b8bc..cae9a813433 100644 --- a/release/ui/space_buttons.py +++ b/release/ui/space_buttons.py @@ -11,7 +11,7 @@ class Buttons_HT_header(bpy.types.Header): so = context.space_data scene = context.scene - layout.template_header(context) + layout.template_header() if context.area.show_menus: row = layout.row(align=True) diff --git a/release/ui/space_filebrowser.py b/release/ui/space_filebrowser.py new file mode 100644 index 00000000000..820134d3e87 --- /dev/null +++ b/release/ui/space_filebrowser.py @@ -0,0 +1,65 @@ + +import bpy + + +class FILEBROWSER_HT_header(bpy.types.Header): + __space_type__ = "FILE_BROWSER" + __idname__ = "FILEBROWSER_HT_header" + + def draw(self, context): + st = context.space_data + layout = self.layout + + params = st.params + layout.template_header() + + if context.area.show_menus: + row = layout.row() + row.itemM("FILEBROWSER_MT_directory") + row.itemM("FILEBROWSER_MT_bookmarks") + + row = layout.row(align=True) + row.itemO("FILE_OT_parent", text="", icon='ICON_FILE_PARENT') + row.itemO("FILE_OT_refresh", text="", icon='ICON_FILE_REFRESH') + + layout.itemR(params, "display", expand=True, text="") + layout.itemR(params, "sort", expand=True, text="") + + layout.itemR(params, "hide_dot") + layout.itemR(params, "do_filter") + + row = layout.row(align=True) + row.itemR(params, "filter_folder", text=""); + row.itemR(params, "filter_blender", text=""); + row.itemR(params, "filter_image", text=""); + row.itemR(params, "filter_movie", text=""); + row.itemR(params, "filter_script", text=""); + row.itemR(params, "filter_font", text=""); + row.itemR(params, "filter_sound", text=""); + row.itemR(params, "filter_text", text=""); + + row.active = params.do_filter + +class FILEBROWSER_MT_directory(bpy.types.Menu): + __space_type__ = "FILE_BROWSER" + __label__ = "Directory" + + def draw(self, context): + layout = self.layout + + layout.itemO("FILE_OT_refresh", text="Refresh", icon='ICON_FILE_REFRESH') + layout.itemO("FILE_OT_parent", text="Parent", icon='ICON_FILE_PARENT') + +class FILEBROWSER_MT_bookmarks(bpy.types.Menu): + __space_type__ = "FILE_BROWSER" + __label__ = "Bookmarks" + + def draw(self, context): + layout = self.layout + + layout.itemO("FILE_OT_add_bookmark", text="Add current directory", icon='ICON_BOOKMARKS') + + +bpy.types.register(FILEBROWSER_HT_header) +bpy.types.register(FILEBROWSER_MT_directory) +bpy.types.register(FILEBROWSER_MT_bookmarks) diff --git a/release/ui/space_image.py b/release/ui/space_image.py index 63ca316efe7..49ef18705c4 100644 --- a/release/ui/space_image.py +++ b/release/ui/space_image.py @@ -96,9 +96,9 @@ class IMAGE_MT_image(bpy.types.Menu): else: layout.itemO("IMAGE_OT_pack") - # only for dirty && specific image types : XXX poll? - #if(ibuf && (ibuf->userflags & IB_BITMAPDIRTY)) - if False: + # only for dirty && specific image types, perhaps + # this could be done in operator poll too + if ima.dirty: if ima.source in ("FILE", "GENERATED") and ima.type != "MULTILAYER": layout.item_booleanO("IMAGE_OT_pack", "as_png", True, text="Pack As PNG") @@ -215,8 +215,10 @@ class IMAGE_HT_header(bpy.types.Header): if show_uvedit: row.itemM("IMAGE_MT_select") - # XXX menuname= (ibuf && (ibuf->userflags & IB_BITMAPDIRTY))? "Image*": "Image"; - row.itemM("IMAGE_MT_image") + if ima and ima.dirty: + row.itemM("IMAGE_MT_image", text="Image*") + else: + row.itemM("IMAGE_MT_image", text="Image") if show_uvedit: row.itemM("IMAGE_MT_uvs") @@ -344,6 +346,10 @@ class IMAGE_PT_view_properties(bpy.types.Panel): __region_type__ = "UI" __label__ = "View Properties" + def poll(self, context): + sima = context.space_data + return (sima and (sima.image or sima.show_uvedit)) + def draw(self, context): sima = context.space_data layout = self.layout @@ -358,10 +364,12 @@ class IMAGE_PT_view_properties(bpy.types.Panel): if ima: col.itemR(ima, "display_aspect") - col = split.column() - col.itemR(sima, "draw_repeated", text="Repeat") - if show_uvedit: - col.itemR(uvedit, "normalized_coordinates") + col = split.column() + col.itemR(sima, "draw_repeated", text="Repeat") + if show_uvedit: + col.itemR(uvedit, "normalized_coordinates", text="Normalized") + elif show_uvedit: + col.itemR(uvedit, "normalized_coordinates", text="Normalized") if show_uvedit: col = layout.column() @@ -377,21 +385,6 @@ class IMAGE_PT_view_properties(bpy.types.Panel): #col.itemR(uvedit, "draw_edges") #col.itemR(uvedit, "draw_faces") -class IMAGE_PT_curves(bpy.types.Panel): - __space_type__ = "IMAGE_EDITOR" - __region_type__ = "UI" - __label__ = "Curves" - - def poll(self, context): - sima = context.space_data - return (sima and sima.image) - - def draw(self, context): - sima = context.space_data - layout = self.layout - - layout.template_curve_mapping(sima.curves) - bpy.types.register(IMAGE_MT_view) bpy.types.register(IMAGE_MT_select) bpy.types.register(IMAGE_MT_image) @@ -403,5 +396,4 @@ bpy.types.register(IMAGE_MT_uvs) bpy.types.register(IMAGE_HT_header) bpy.types.register(IMAGE_PT_game_properties) bpy.types.register(IMAGE_PT_view_properties) -#bpy.types.register(IMAGE_PT_curves) diff --git a/release/ui/space_info.py b/release/ui/space_info.py new file mode 100644 index 00000000000..de3346711e9 --- /dev/null +++ b/release/ui/space_info.py @@ -0,0 +1,119 @@ + +import bpy + +class INFO_HT_header(bpy.types.Header): + __space_type__ = "USER_PREFERENCES" + __idname__ = "INFO_HT_header" + + def draw(self, context): + st = context.space_data + layout = self.layout + + layout.template_header() + + if context.area.show_menus: + row = layout.row() + row.itemM("INFO_MT_file") + row.itemM("INFO_MT_add") + row.itemM("INFO_MT_timeline") + row.itemM("INFO_MT_game") + row.itemM("INFO_MT_render") + row.itemM("INFO_MT_help") + + layout.template_ID(context.window, "screen") #, new="SCREEN_OT_new", open="SCREEN_OT_unlink") + layout.template_ID(context.screen, "scene") #, new="SCENE_OT_new", unlink="SCENE_OT_unlink") + + layout.itemS() + + layout.template_operator_search() + layout.template_running_jobs() + +class INFO_MT_file(bpy.types.Menu): + __space_type__ = "USER_PREFERENCES" + __label__ = "File" + + def draw(self, context): + layout = self.layout + + layout.operator_context = "EXEC_AREA" + layout.itemO("WM_OT_read_homefile") + layout.operator_context = "INVOKE_AREA" + layout.itemO("WM_OT_open_mainfile") + + layout.itemS() + + layout.operator_context = "EXEC_AREA" + layout.itemO("WM_OT_save_mainfile") + layout.operator_context = "INVOKE_AREA" + layout.itemO("WM_OT_save_as_mainfile") + + layout.itemS() + + layout.itemM("INFO_MT_file_external_data") + +class INFO_MT_file_external_data(bpy.types.Menu): + __space_type__ = "USER_PREFERENCES" + __label__ = "External Data" + + def draw(self, context): + layout = self.layout + + layout.itemO("FILE_OT_pack_all", text="Pack into .blend file") + layout.itemO("FILE_OT_unpack_all", text="Unpack into Files...") + + layout.itemS() + + layout.itemO("FILE_OT_make_paths_relative") + layout.itemO("FILE_OT_make_paths_absolute") + layout.itemO("FILE_OT_report_missing_files") + layout.itemO("FILE_OT_find_missing_files") + +class INFO_MT_add(bpy.types.Menu): + __space_type__ = "USER_PREFERENCES" + __label__ = "Add" + + def draw(self, context): + layout = self.layout + layout.itemL(text="Nothing yet") + +class INFO_MT_timeline(bpy.types.Menu): + __space_type__ = "USER_PREFERENCES" + __label__ = "Timeline" + + def draw(self, context): + layout = self.layout + layout.itemL(text="Nothing yet") + +class INFO_MT_game(bpy.types.Menu): + __space_type__ = "USER_PREFERENCES" + __label__ = "Game" + + def draw(self, context): + layout = self.layout + layout.itemL(text="Nothing yet") + +class INFO_MT_render(bpy.types.Menu): + __space_type__ = "USER_PREFERENCES" + __label__ = "Render" + + def draw(self, context): + layout = self.layout + layout.itemL(text="Nothing yet") + +class INFO_MT_help(bpy.types.Menu): + __space_type__ = "USER_PREFERENCES" + __label__ = "Help" + + def draw(self, context): + layout = self.layout + layout.itemL(text="Nothing yet") + +bpy.types.register(INFO_HT_header) +bpy.types.register(INFO_MT_file) +bpy.types.register(INFO_MT_file_external_data) +bpy.types.register(INFO_MT_add) +bpy.types.register(INFO_MT_timeline) +bpy.types.register(INFO_MT_game) +bpy.types.register(INFO_MT_render) +bpy.types.register(INFO_MT_help) + diff --git a/source/blender/blenkernel/BKE_packedFile.h b/source/blender/blenkernel/BKE_packedFile.h index 2d5acc51b7b..efd930d375a 100644 --- a/source/blender/blenkernel/BKE_packedFile.h +++ b/source/blender/blenkernel/BKE_packedFile.h @@ -31,31 +31,43 @@ #ifndef BKE_PACKEDFILE_H #define BKE_PACKEDFILE_H -#define RET_OK 0 -#define RET_ERROR 1 +#define RET_OK 0 +#define RET_ERROR 1 -struct PackedFile; -struct VFont; struct bSample; struct bSound; struct Image; +struct Main; +struct PackedFile; +struct ReportList; +struct VFont; -struct PackedFile * newPackedFile(char * filename); -struct PackedFile * newPackedFileMemory(void *mem, int memlen); +/* pack */ +struct PackedFile *newPackedFile(struct ReportList *reports, char *filename); +struct PackedFile *newPackedFileMemory(void *mem, int memlen); + +void packAll(struct Main *bmain, struct ReportList *reports); + +/* unpack */ +char *unpackFile(struct ReportList *reports, char *abs_name, char *local_name, struct PackedFile *pf, int how); +int unpackVFont(struct ReportList *reports, struct VFont *vfont, int how); +int unpackSample(struct ReportList *reports, struct bSample *sample, int how); +int unpackImage(struct ReportList *reports, struct Image *ima, int how); +void unpackAll(struct Main *bmain, struct ReportList *reports, int how); + +int writePackedFile(struct ReportList *reports, char *filename, struct PackedFile *pf, int guimode); + +/* free */ +void freePackedFile(struct PackedFile *pf); + +/* info */ +int countPackedFiles(struct Main *bmain); +int checkPackedFile(char *filename, struct PackedFile *pf); + +/* read */ +int seekPackedFile(struct PackedFile *pf, int offset, int whence); +void rewindPackedFile(struct PackedFile *pf); +int readPackedFile(struct PackedFile *pf, void *data, int size); -int seekPackedFile(struct PackedFile * pf, int offset, int whence); -void rewindPackedFile(struct PackedFile * pf); -int readPackedFile(struct PackedFile * pf, void * data, int size); -int countPackedFiles(void); -void freePackedFile(struct PackedFile * pf); -void packAll(void); -int writePackedFile(char * filename, struct PackedFile *pf, int guimode); -int checkPackedFile(char * filename, struct PackedFile * pf); -char * unpackFile(char * abs_name, char * local_name, struct PackedFile * pf, int how); -int unpackVFont(struct VFont * vfont, int how); -int unpackSample(struct bSample *sample, int how); -int unpackImage(struct Image * ima, int how); -void unpackAll(int how); - #endif diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 4d9916b9557..73f0195d1d8 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -251,8 +251,8 @@ void copy_particle_key(struct ParticleKey *to, struct ParticleKey *from, int tim void psys_particle_on_emitter(struct ParticleSystemModifierData *psmd, int distr, int index, int index_dmcache, float *fuv, float foffset, float *vec, float *nor, float *utan, float *vtan, float *orco, float *ornor); struct ParticleSystemModifierData *psys_get_modifier(struct Object *ob, struct ParticleSystem *psys); -void object_add_particle_system_slot(struct Scene *scene, struct Object *ob); -void object_remove_particle_system_slot(struct Scene *scene, struct Object *ob); +void object_add_particle_system(struct Scene *scene, struct Object *ob); +void object_remove_particle_system(struct Scene *scene, struct Object *ob); struct ParticleSettings *psys_new_settings(char *name, struct Main *main); struct ParticleSettings *psys_copy_settings(struct ParticleSettings *part); void psys_flush_particle_settings(struct Scene *scene, struct ParticleSettings *part, int recalc); diff --git a/source/blender/blenkernel/BKE_report.h b/source/blender/blenkernel/BKE_report.h index 21221026b8b..1bb7152fbf3 100644 --- a/source/blender/blenkernel/BKE_report.h +++ b/source/blender/blenkernel/BKE_report.h @@ -34,7 +34,10 @@ extern "C" { #include "DNA_listBase.h" -/* Reporting Information and Errors */ +/* Reporting Information and Errors + * + * These functions also accept NULL in case no error reporting + * is needed. */ typedef enum ReportType { RPT_DEBUG = 0, diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 57ef920f75b..706eece108c 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -1220,7 +1220,7 @@ void CDDM_calc_edges(DerivedMesh *dm) BLI_edgehashIterator_free(ehi); /* free old CustomData and assign new one */ - CustomData_free(&dm->edgeData, dm->numVertData); + CustomData_free(&dm->edgeData, dm->numEdgeData); dm->edgeData = edgeData; dm->numEdgeData = numEdges; diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index 90880e354ec..fbad585d9b7 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -358,6 +358,9 @@ static int ctx_data_collection_get(const bContext *C, const char *member, ListBa return 1; } + list->first= NULL; + list->last= NULL; + return 0; } diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 736165a8a98..cdf4b90cee1 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -315,13 +315,19 @@ static void init_fastshade_shadeinput(Render *re) static Render *fastshade_get_render(Scene *scene) { - Render *re= RE_GetRender("_Shade View_"); - if(re==NULL) { - re= RE_NewRender("_Shade View_"); - - RE_Database_Baking(re, scene, 0, 0); /* 0= no faces */ + /* XXX ugly global still, but we can't do preview while rendering */ + if(G.rendering==0) { + + Render *re= RE_GetRender("_Shade View_"); + if(re==NULL) { + re= RE_NewRender("_Shade View_"); + + RE_Database_Baking(re, scene, 0, 0); /* 0= no faces */ + } + return re; } - return re; + + return NULL; } /* called on file reading */ @@ -611,18 +617,20 @@ static void mesh_create_shadedColors(Render *re, Object *ob, int onlyForMesh, un void shadeMeshMCol(Scene *scene, Object *ob, Mesh *me) { + Render *re= fastshade_get_render(scene); int a; char *cp; unsigned int *mcol= (unsigned int*)me->mcol; - Render *re= fastshade_get_render(scene); - mesh_create_shadedColors(re, ob, 1, &mcol, NULL); - me->mcol= (MCol*)mcol; + if(re) { + mesh_create_shadedColors(re, ob, 1, &mcol, NULL); + me->mcol= (MCol*)mcol; - /* swap bytes */ - for(cp= (char *)me->mcol, a= 4*me->totface; a>0; a--, cp+=4) { - SWAP(char, cp[0], cp[3]); - SWAP(char, cp[1], cp[2]); + /* swap bytes */ + for(cp= (char *)me->mcol, a= 4*me->totface; a>0; a--, cp+=4) { + SWAP(char, cp[0], cp[3]); + SWAP(char, cp[1], cp[2]); + } } } @@ -641,6 +649,8 @@ void shadeDispList(Scene *scene, Base *base) int a, need_orco; re= fastshade_get_render(scene); + if(re==NULL) + return; dl = find_displist(&ob->disp, DL_VERTCOL); if (dl) { diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index 60a7ffc28d9..70901778585 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -333,11 +333,11 @@ static VFontData *vfont_get_data(VFont *vfont) BLI_addtail(&ttfdata, tmpfnt); } } else { - pf= newPackedFile(vfont->name); + pf= newPackedFile(NULL, vfont->name); if(!tmpfnt) { - tpf= newPackedFile(vfont->name); + tpf= newPackedFile(NULL, vfont->name); // Add temporary packed file to globals tmpfnt= (struct TmpFont *) MEM_callocN(sizeof(struct TmpFont), "temp_font"); @@ -385,8 +385,8 @@ VFont *load_vfont(char *name) strcpy(dir, name); BLI_splitdirstring(dir, filename); - pf= newPackedFile(name); - tpf= newPackedFile(name); + pf= newPackedFile(NULL, name); + tpf= newPackedFile(NULL, name); is_builtin= 0; } diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 8eef9984c92..ef0984bf93d 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -1431,7 +1431,7 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal) /* try to repack file */ if(ima->packedfile) { PackedFile *pf; - pf = newPackedFile(ima->name); + pf = newPackedFile(NULL, ima->name); if (pf) { freePackedFile(ima->packedfile); ima->packedfile = pf; @@ -1750,7 +1750,7 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra) /* make packed file for autopack */ if ((ima->packedfile == NULL) && (G.fileflags & G_AUTOPACK)) - ima->packedfile = newPackedFile(str); + ima->packedfile = newPackedFile(NULL, str); } if(ima->flag & IMA_DO_PREMUL) @@ -1812,7 +1812,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser) Render *re= NULL; RenderResult *rr= NULL; - if(iuser->scene) { + if(iuser && iuser->scene) { re= RE_GetRender(iuser->scene->id.name); rr= RE_GetResult(re); } diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c index 22e4e8a8309..4d88556d8bf 100644 --- a/source/blender/blenkernel/intern/packedFile.c +++ b/source/blender/blenkernel/intern/packedFile.c @@ -61,8 +61,9 @@ #include "BKE_image.h" #include "BKE_font.h" #include "BKE_packedFile.h" +#include "BKE_report.h" -int seekPackedFile(PackedFile * pf, int offset, int whence) +int seekPackedFile(PackedFile *pf, int offset, int whence) { int oldseek = -1, seek = 0; @@ -92,12 +93,12 @@ int seekPackedFile(PackedFile * pf, int offset, int whence) return(oldseek); } -void rewindPackedFile(PackedFile * pf) +void rewindPackedFile(PackedFile *pf) { seekPackedFile(pf, 0, SEEK_SET); } -int readPackedFile(PackedFile * pf, void * data, int size) +int readPackedFile(PackedFile *pf, void *data, int size) { if ((pf != NULL) && (size >= 0) && (data != NULL)) { if (size + pf->seek > pf->size) { @@ -118,66 +119,55 @@ int readPackedFile(PackedFile * pf, void * data, int size) return(size); } -int countPackedFiles() +int countPackedFiles(Main *bmain) { - int count = 0; Image *ima; VFont *vf; bSample *sample; + int count = 0; // let's check if there are packed files... - ima = G.main->image.first; - while (ima) { - if (ima->packedfile) { + for(ima=bmain->image.first; ima; ima=ima->id.next) + if(ima->packedfile) count++; - } - ima= ima->id.next; - } - vf = G.main->vfont.first; - while (vf) { - if (vf->packedfile) { + for(vf=bmain->vfont.first; vf; vf=vf->id.next) + if(vf->packedfile) count++; - } - vf = vf->id.next; - } - sample = samples->first; - while (sample) { - if (sample->packedfile) { - count++; - } - sample = sample->id.next; - } + if(samples) + for(sample=samples->first; sample; sample=sample->id.next) + if(sample->packedfile) + count++; - return(count); + return count; } -void freePackedFile(PackedFile * pf) +void freePackedFile(PackedFile *pf) { - if (pf) { + if(pf) { MEM_freeN(pf->data); MEM_freeN(pf); - } else { - printf("freePackedFile: Trying to free a NULL pointer\n"); } + else + printf("freePackedFile: Trying to free a NULL pointer\n"); } -PackedFile * newPackedFileMemory(void *mem, int memlen) +PackedFile *newPackedFileMemory(void *mem, int memlen) { - PackedFile * pf = MEM_callocN(sizeof(*pf), "PackedFile"); + PackedFile *pf = MEM_callocN(sizeof(*pf), "PackedFile"); pf->data = mem; pf->size = memlen; return pf; } -PackedFile * newPackedFile(char * filename) +PackedFile *newPackedFile(ReportList *reports, char *filename) { - PackedFile * pf = NULL; + PackedFile *pf = NULL; int file, filelen; char name[FILE_MAXDIR+FILE_MAXFILE]; - void * data; + void *data; //XXX waitcursor(1); @@ -191,7 +181,7 @@ PackedFile * newPackedFile(char * filename) file= open(name, O_BINARY|O_RDONLY); if (file <= 0) { - // error("Can't open file: %s", name); + BKE_reportf(reports, RPT_ERROR, "Can't open file: %s", name); } else { filelen = BLI_filesize(file); @@ -214,36 +204,24 @@ PackedFile * newPackedFile(char * filename) return (pf); } -void packAll() +void packAll(Main *bmain, ReportList *reports) { Image *ima; VFont *vf; bSample *sample; - ima = G.main->image.first; - while (ima) { - if (ima->packedfile == NULL) { - ima->packedfile = newPackedFile(ima->name); - } - ima= ima->id.next; - } - - vf = G.main->vfont.first; - while (vf) { - if (vf->packedfile == NULL) { - vf->packedfile = newPackedFile(vf->name); - } - vf = vf->id.next; - } + for(ima=bmain->image.first; ima; ima=ima->id.next) + if(ima->packedfile == NULL) + ima->packedfile = newPackedFile(reports, ima->name); + for(vf=bmain->vfont.first; vf; vf=vf->id.next) + if(vf->packedfile == NULL) + vf->packedfile = newPackedFile(reports, vf->name); - sample = samples->first; - while (sample) { - if (sample->packedfile == NULL) { - sound_set_packedfile(sample, newPackedFile(sample->name)); - } - sample = sample->id.next; - } + if(samples) + for(sample=samples->first; sample; sample=sample->id.next) + if(sample->packedfile == NULL) + sound_set_packedfile(sample, newPackedFile(reports, sample->name)); } @@ -252,10 +230,10 @@ void packAll() // 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) +char *find_new_name(char *name) { char tempname[FILE_MAXDIR + FILE_MAXFILE]; - char * newname; + char *newname; if (fop_exists(name)) { for (number = 1; number <= 999; number++) { @@ -274,13 +252,13 @@ char * find_new_name(char * name) */ -int writePackedFile(char * filename, PackedFile *pf, int guimode) +int writePackedFile(ReportList *reports, char *filename, PackedFile *pf, int guimode) { int file, number, remove_tmp = FALSE; int ret_value = RET_OK; char name[FILE_MAXDIR + FILE_MAXFILE]; char tempname[FILE_MAXDIR + FILE_MAXFILE]; -/* void * data; */ +/* void *data; */ if (guimode); //XXX waitcursor(1); @@ -305,23 +283,23 @@ int writePackedFile(char * filename, PackedFile *pf, int guimode) file = open(name, O_BINARY + O_WRONLY + O_CREAT + O_TRUNC, 0666); if (file >= 0) { if (write(file, pf->data, pf->size) != pf->size) { - if(guimode) ; //XXX error("Error writing file: %s", name); + BKE_reportf(reports, RPT_ERROR, "Error writing file: %s", name); ret_value = RET_ERROR; } close(file); } else { - if(guimode); //XXX error("Error creating file: %s", name); + BKE_reportf(reports, RPT_ERROR, "Error creating file: %s", name); ret_value = RET_ERROR; } if (remove_tmp) { if (ret_value == RET_ERROR) { if (BLI_rename(tempname, name) != 0) { - if(guimode); //XXX error("Error restoring tempfile. Check files: '%s' '%s'", tempname, name); + BKE_reportf(reports, RPT_ERROR, "Error restoring tempfile. Check files: '%s' '%s'", tempname, name); } } else { if (BLI_delete(tempname, 0, 0) != 0) { - if(guimode); //XXX error("Error deleting '%s' (ignored)"); + BKE_reportf(reports, RPT_ERROR, "Error deleting '%s' (ignored)", tempname); } } } @@ -342,7 +320,7 @@ PF_NOFILE - the original file doens't exist */ -int checkPackedFile(char * filename, PackedFile * pf) +int checkPackedFile(char *filename, PackedFile *pf) { struct stat st; int ret_val, i, len, file; @@ -390,68 +368,23 @@ int checkPackedFile(char * filename, PackedFile * pf) /* -unpackFile() looks at the existing files (abs_name, local_name) and a packed file. -If how == PF_ASK it offers the user a couple of options what to do with the packed file. + unpackFile() looks at the existing files (abs_name, local_name) and a packed file. -It returns a char * to the existing file name / new file name or NULL when +It returns a char *to the existing file name / new file name or NULL when there was an error or when the user desides to cancel the operation. */ -char *unpackFile(char * abs_name, char * local_name, PackedFile * pf, int how) +char *unpackFile(ReportList *reports, char *abs_name, char *local_name, PackedFile *pf, int how) { - char menu[6 * (FILE_MAXDIR + FILE_MAXFILE + 100)]; + char menu[6 *(FILE_MAXDIR + FILE_MAXFILE + 100)]; char line[FILE_MAXDIR + FILE_MAXFILE + 100]; - char * newname = NULL, * temp = NULL; + char *newname = NULL, *temp = NULL; // char newabs[FILE_MAXDIR + FILE_MAXFILE]; // char newlocal[FILE_MAXDIR + FILE_MAXFILE]; if (pf != NULL) { - if (how == PF_ASK) { - sprintf(menu, "UnPack file%%t|Remove Pack %%x%d", PF_REMOVE); - - if (strcmp(abs_name, local_name)) { - switch (checkPackedFile(local_name, pf)) { - case PF_NOFILE: - sprintf(line, "|Create %s%%x%d", local_name, PF_WRITE_LOCAL); - strcat(menu, line); - break; - case PF_EQUAL: - sprintf(line, "|Use %s (identical)%%x%d", local_name, PF_USE_LOCAL); - strcat(menu, line); - break; - case PF_DIFFERS: - sprintf(line, "|Use %s (differs)%%x%d", local_name, PF_USE_LOCAL); - strcat(menu, line); - sprintf(line, "|Overwrite %s%%x%d", local_name, PF_WRITE_LOCAL); - strcat(menu, line); - break; - } - // sprintf(line, "|%%x%d", PF_INVALID); - // strcat(menu, line); - } - - switch (checkPackedFile(abs_name, pf)) { - case PF_NOFILE: - sprintf(line, "|Create %s%%x%d", abs_name, PF_WRITE_ORIGINAL); - strcat(menu, line); - break; - case PF_EQUAL: - sprintf(line, "|Use %s (identical)%%x%d", abs_name, PF_USE_ORIGINAL); - strcat(menu, line); - break; - case PF_DIFFERS: - sprintf(line, "|Use %s (differs)%%x%d", abs_name, PF_USE_ORIGINAL); - strcat(menu, line); - sprintf(line, "|Overwrite %s%%x%d", abs_name, PF_WRITE_ORIGINAL); - strcat(menu, line); - break; - } - - //XXX how = pupmenu(menu); - } - switch (how) { case -1: case PF_KEEP: @@ -467,7 +400,7 @@ char *unpackFile(char * abs_name, char * local_name, PackedFile * pf, int how) } // else fall through and create it case PF_WRITE_LOCAL: - if (writePackedFile(local_name, pf, 1) == RET_OK) { + if (writePackedFile(reports, local_name, pf, 1) == RET_OK) { temp = local_name; } break; @@ -479,7 +412,7 @@ char *unpackFile(char * abs_name, char * local_name, PackedFile * pf, int how) } // else fall through and create it case PF_WRITE_ORIGINAL: - if (writePackedFile(abs_name, pf, 1) == RET_OK) { + if (writePackedFile(reports, abs_name, pf, 1) == RET_OK) { temp = abs_name; } break; @@ -498,10 +431,10 @@ char *unpackFile(char * abs_name, char * local_name, PackedFile * pf, int how) } -int unpackVFont(VFont * vfont, int how) +int unpackVFont(ReportList *reports, VFont *vfont, int how) { char localname[FILE_MAXDIR + FILE_MAXFILE], fi[FILE_MAXFILE]; - char * newname; + char *newname; int ret_value = RET_ERROR; if (vfont != NULL) { @@ -510,7 +443,7 @@ int unpackVFont(VFont * vfont, int how) sprintf(localname, "//fonts/%s", fi); - newname = unpackFile(vfont->name, localname, vfont->packedfile, how); + newname = unpackFile(reports, vfont->name, localname, vfont->packedfile, how); if (newname != NULL) { ret_value = RET_OK; freePackedFile(vfont->packedfile); @@ -523,10 +456,10 @@ int unpackVFont(VFont * vfont, int how) return (ret_value); } -int unpackSample(bSample *sample, int how) +int unpackSample(ReportList *reports, bSample *sample, int how) { char localname[FILE_MAXDIR + FILE_MAX], fi[FILE_MAX]; - char * newname; + char *newname; int ret_value = RET_ERROR; PackedFile *pf; @@ -535,7 +468,7 @@ int unpackSample(bSample *sample, int how) BLI_splitdirstring(localname, fi); sprintf(localname, "//samples/%s", fi); - newname = unpackFile(sample->name, localname, sample->packedfile, how); + newname = unpackFile(reports, sample->name, localname, sample->packedfile, how); if (newname != NULL) { strcpy(sample->name, newname); MEM_freeN(newname); @@ -553,10 +486,10 @@ int unpackSample(bSample *sample, int how) return(ret_value); } -int unpackImage(Image * ima, int how) +int unpackImage(ReportList *reports, Image *ima, int how) { char localname[FILE_MAXDIR + FILE_MAX], fi[FILE_MAX]; - char * newname; + char *newname; int ret_value = RET_ERROR; if (ima != NULL) { @@ -564,7 +497,7 @@ int unpackImage(Image * ima, int how) BLI_splitdirstring(localname, fi); sprintf(localname, "//textures/%s", fi); - newname = unpackFile(ima->name, localname, ima->packedfile, how); + newname = unpackFile(reports, ima->name, localname, ima->packedfile, how); if (newname != NULL) { ret_value = RET_OK; freePackedFile(ima->packedfile); @@ -578,33 +511,23 @@ int unpackImage(Image * ima, int how) return(ret_value); } -void unpackAll(int how) +void unpackAll(Main *bmain, ReportList *reports, int how) { Image *ima; VFont *vf; bSample *sample; - - ima = G.main->image.first; - while (ima) { - if (ima->packedfile) { - unpackImage(ima, how); - } - ima= ima->id.next; - } - - vf = G.main->vfont.first; - while (vf) { - if (vf->packedfile) { - unpackVFont(vf, how); - } - vf = vf->id.next; - } - sample = samples->first; - while (sample) { - if (sample->packedfile) { - unpackSample(sample, how); - } - sample = sample->id.next; - } + for(ima=bmain->image.first; ima; ima=ima->id.next) + if(ima->packedfile) + unpackImage(reports, ima, how); + + for(vf=bmain->vfont.first; vf; vf=vf->id.next) + if(vf->packedfile) + unpackVFont(reports, vf, how); + + if(samples) + for(sample=samples->first; sample; sample=sample->id.next) + if(sample->packedfile) + unpackSample(reports, sample, how); } + diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 2474053298d..5bf9335d211 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -230,7 +230,7 @@ void psys_set_current_num(Object *ob, int index) if(ob==0) return; for(psys=ob->particlesystem.first, i=0; psys; psys=psys->next, i++) { - if(i == index - 1) + if(i == index) psys->flag |= PSYS_CURRENT; else psys->flag &= ~PSYS_CURRENT; @@ -2929,7 +2929,7 @@ void psys_mat_hair_to_global(Object *ob, DerivedMesh *dm, short from, ParticleDa /************************************************/ /* ParticleSettings handling */ /************************************************/ -void object_add_particle_system_slot(Scene *scene, Object *ob) +void object_add_particle_system(Scene *scene, Object *ob) { ParticleSystem *psys; ModifierData *md; @@ -2961,7 +2961,7 @@ void object_add_particle_system_slot(Scene *scene, Object *ob) DAG_scene_sort(scene); DAG_object_flush_update(scene, ob, OB_RECALC_DATA); } -void object_remove_particle_system_slot(Scene *scene, Object *ob) +void object_remove_particle_system(Scene *scene, Object *ob) { ParticleSystem *psys = psys_get_current(ob); ParticleSystemModifierData *psmd; diff --git a/source/blender/blenkernel/intern/report.c b/source/blender/blenkernel/intern/report.c index 116fd069948..8de8cf8d0f4 100644 --- a/source/blender/blenkernel/intern/report.c +++ b/source/blender/blenkernel/intern/report.c @@ -65,8 +65,8 @@ void BKE_reports_init(ReportList *reports, int flag) memset(reports, 0, sizeof(ReportList)); - reports->storelevel= RPT_WARNING; - reports->printlevel= RPT_WARNING; + reports->storelevel= RPT_INFO; + reports->printlevel= RPT_INFO; reports->flag= flag; } diff --git a/source/blender/blenlib/BLI_util.h b/source/blender/blenlib/BLI_util.h index 30c9fc353b3..a138ea780ea 100644 --- a/source/blender/blenlib/BLI_util.h +++ b/source/blender/blenlib/BLI_util.h @@ -50,6 +50,7 @@ void BLI_make_existing_file(char *name); void BLI_split_dirfile(char *string, char *dir, char *file); void BLI_split_dirfile_basic(const char *string, char *dir, char *file); void BLI_join_dirfile(char *string, const char *dir, const char *file); +void BLI_getlastdir(const char* dir, char *last, int maxlen); int BLI_testextensie(const char *str, const char *ext); void BLI_uniquename(struct ListBase *list, void *vlink, char defname[], char delim, short name_offs, short len); void BLI_newname(char * name, int add); diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c index 0ae17a13e43..3204d5f74e1 100644 --- a/source/blender/blenlib/intern/storage.c +++ b/source/blender/blenlib/intern/storage.c @@ -218,7 +218,7 @@ void BLI_builddir(char *dirname, char *relname) { struct dirent *fname; struct dirlink *dlink; - int rellen, newnum = 0, seen_ = 0, seen__ = 0; + int rellen, newnum = 0, ignore; char buf[256]; DIR *dir; @@ -238,21 +238,17 @@ void BLI_builddir(char *dirname, char *relname) if ( (dir = (DIR *)opendir(".")) ){ while ((fname = (struct dirent*) readdir(dir)) != NULL) { - if(hide_dot && fname->d_name[0]=='.' && fname->d_name[1]!='.' && fname->d_name[1]!=0); + if(hide_dot && fname->d_name[0]=='.' && fname->d_name[1]!='.' && fname->d_name[1]!=0) { + } + else if ( ( (fname->d_name[0] == '.') && (fname->d_name[1] == 0) ) || + ( (fname->d_name[0] == '.') && (fname->d_name[1] == '.') && (fname->d_name[2] == 0)) ) { + /* ignore '.' and '..' */ + } else { - dlink = (struct dirlink *)malloc(sizeof(struct dirlink)); if (dlink){ strcpy(buf+rellen,fname->d_name); - dlink->name = BLI_strdup(buf); - - if (dlink->name[0] == '.') { - if (dlink->name[1] == 0) seen_ = 1; - else if (dlink->name[1] == '.') { - if (dlink->name[2] == 0) seen__ = 1; - } - } BLI_addhead(dirbase,dlink); newnum++; } @@ -260,30 +256,6 @@ void BLI_builddir(char *dirname, char *relname) } if (newnum){ -#ifndef WIN32 - if (seen_ == 0) { /* Cachefs PATCH */ - dlink = (struct dirlink *)malloc(sizeof(struct dirlink)); - strcpy(buf+rellen,"./."); - dlink->name = BLI_strdup(buf); - BLI_addhead(dirbase,dlink); - newnum++; - } - if (seen__ == 0) { /* MAC PATCH */ - dlink = (struct dirlink *)malloc(sizeof(struct dirlink)); - strcpy(buf+rellen,"./.."); - dlink->name = BLI_strdup(buf); - BLI_addhead(dirbase,dlink); - newnum++; - } -#else // WIN32 - if (seen_ == 0) { /* should only happen for root paths like "C:\" */ - dlink = (struct dirlink *)malloc(sizeof(struct dirlink)); - strcpy(buf+rellen,"."); - dlink->name = BLI_strdup(buf); - BLI_addhead(dirbase,dlink); - newnum++; - } -#endif if (files) files=(struct direntry *)realloc(files,(totnum+newnum) * sizeof(struct direntry)); else files=(struct direntry *)malloc(newnum * sizeof(struct direntry)); diff --git a/source/blender/blenlib/intern/util.c b/source/blender/blenlib/intern/util.c index 26f4c2dd415..b9d4daaf5b2 100644 --- a/source/blender/blenlib/intern/util.c +++ b/source/blender/blenlib/intern/util.c @@ -736,6 +736,25 @@ void BLI_splitdirstring(char *di, char *fi) } } +void BLI_getlastdir(const char* dir, char *last, int maxlen) +{ + char *s = dir; + char *lslash = NULL; + char *prevslash = NULL; + while (*s) { + if ((*s == '\\') || (*s == '/')) { + prevslash = lslash; + lslash = s; + } + s++; + } + if (prevslash) { + BLI_strncpy(last, prevslash+1, maxlen); + } else { + BLI_strncpy(last, dir, maxlen); + } +} + char *BLI_gethome(void) { #if !defined(WIN32) return getenv("HOME"); diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 6df907fe132..0c1ba32c543 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -5658,21 +5658,6 @@ static void area_add_window_regions(ScrArea *sa, SpaceLink *sl, ListBase *lb) /* temporarily hide it */ ar->flag = RGN_FLAG_HIDDEN; break; - - case SPACE_FILE: - /* channel (bookmarks/directories) region */ - ar= MEM_callocN(sizeof(ARegion), "area region from do_versions"); - BLI_addtail(lb, ar); - ar->regiontype= RGN_TYPE_CHANNELS; - ar->alignment= RGN_ALIGN_LEFT; - ar->v2d.scroll= V2D_SCROLL_RIGHT; - /* button UI region */ - ar= MEM_callocN(sizeof(ARegion), "area region from do_versions"); - BLI_addtail(lb, ar); - ar->regiontype= RGN_TYPE_UI; - ar->alignment= RGN_ALIGN_TOP; - break; - #if 0 case SPACE_BUTS: /* context UI region */ @@ -9089,12 +9074,14 @@ static void do_versions(FileData *fd, Library *lib, Main *main) */ //do_versions_ipos_to_animato(main); - /* struct audio data moved to renderdata */ + /* toolsettings */ for(scene= main->scene.first; scene; scene= scene->id.next) { scene->r.audio = scene->audio; - if(!scene->toolsettings->uv_selectmode) + if(!scene->toolsettings->uv_selectmode) { scene->toolsettings->uv_selectmode= UV_SELECT_VERTEX; + scene->toolsettings->vgroup_weight= 1.0f; + } } /* shader, composit and texture node trees have id.name empty, put something in diff --git a/source/blender/editors/include/ED_fileselect.h b/source/blender/editors/include/ED_fileselect.h index 34aefa91225..01882ecd9bc 100644 --- a/source/blender/editors/include/ED_fileselect.h +++ b/source/blender/editors/include/ED_fileselect.h @@ -29,34 +29,8 @@ #define ED_FILES_H struct SpaceFile; - -#define FILE_SHORTDISPLAY 1 -#define FILE_LONGDISPLAY 2 -#define FILE_IMGDISPLAY 3 - -typedef struct FileSelectParams { - char title[24]; /* title, also used for the text of the execute button */ - char dir[240]; /* directory */ - char file[80]; /* file */ - - short flag; /* settings for filter, hiding files and display mode */ - short sort; /* sort order */ - short display; /* display mode flag */ - short filter; /* filter when (flags & FILE_FILTER) is true */ - - /* XXX - temporary, better move to filelist */ - short active_bookmark; - int active_file; - int selstate; - - /* XXX --- still unused -- */ - short f_fp; /* show font preview */ - char fp_str[8]; /* string to use for font preview */ - - char *pupmenu; /* allows menu for save options - result stored in menup */ - short menu; /* currently selected option in pupmenu */ - /* XXX --- end unused -- */ -} FileSelectParams; +struct ARegion; +struct FileSelectParams; #define FILE_LAYOUT_HOR 1 #define FILE_LAYOUT_VER 2 @@ -93,7 +67,7 @@ typedef struct FileLayout float column_widths[MAX_FILE_COLUMN]; } FileLayout; -FileSelectParams* ED_fileselect_get_params(struct SpaceFile *sfile); +struct FileSelectParams* ED_fileselect_get_params(struct SpaceFile *sfile); short ED_fileselect_set_params(struct SpaceFile *sfile, const char *title, const char *path, short flag, short display, short filter, short sort); diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index 937f6384f6a..8952305d6ab 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -110,7 +110,6 @@ void undo_push_mesh(struct bContext *C, char *name); struct EditFace *EM_get_actFace(struct EditMesh *em, int sloppy); void EM_set_actFace(struct EditMesh *em, struct EditFace *efa); float EM_face_area(struct EditFace *efa); -void EM_add_data_layer(struct EditMesh *em, struct CustomData *data, int type); void EM_select_edge(struct EditEdge *eed, int sel); void EM_select_face(struct EditFace *efa, int sel); @@ -134,6 +133,9 @@ struct UvVertMap *EM_make_uv_vert_map(struct EditMesh *em, int selected, int do_ struct UvMapVert *EM_get_uv_map_vert(struct UvVertMap *vmap, unsigned int v); void EM_free_uv_vert_map(struct UvVertMap *vmap); +void EM_add_data_layer(struct EditMesh *em, struct CustomData *data, int type); +void EM_free_data_layer(struct EditMesh *em, struct CustomData *data, int type); + /* editmesh_mods.c */ extern unsigned int em_vertoffs, em_solidoffs, em_wireoffs; diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index b6d71759373..cc8b936b04f 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -456,7 +456,7 @@ typedef void (*uiBlockHandleFunc)(struct bContext *C, void *arg, int event); /* use inside searchfunc to add items */ int uiSearchItemAdd(uiSearchItems *items, const char *name, void *poin, int iconid); /* bfunc gets search item *poin as arg2, or if NULL the old string */ -void uiButSetSearchFunc (uiBut *but, uiButSearchFunc sfunc, void *arg1, uiButHandleFunc bfunc); +void uiButSetSearchFunc (uiBut *but, uiButSearchFunc sfunc, void *arg1, uiButHandleFunc bfunc, void *active); /* height in pixels, it's using hardcoded values still */ int uiSearchBoxhHeight(void); @@ -617,7 +617,9 @@ void uiTemplateColorRamp(uiLayout *layout, struct ColorBand *coba, int expand); void uiTemplateCurveMapping(uiLayout *layout, struct CurveMapping *cumap, int type); void uiTemplateLayers(uiLayout *layout, struct PointerRNA *ptr, char *propname); void uiTemplateImageLayers(uiLayout *layout, struct bContext *C, struct Image *ima, struct ImageUser *iuser); -ListBase uiTemplateList(uiLayout *layout, struct PointerRNA *ptr, char *propname, char *activeprop, int rows, int columns, int compact); +ListBase uiTemplateList(uiLayout *layout, struct PointerRNA *ptr, char *propname, struct PointerRNA *activeptr, char *activeprop, int rows, int columns, int compact); +void uiTemplateRunningJobs(uiLayout *layout, struct bContext *C); +void uiTemplateOperatorSearch(uiLayout *layout); /* items */ void uiItemO(uiLayout *layout, char *name, int icon, char *opname); diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index a9866d8898e..00ec875bd86 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -2184,7 +2184,7 @@ uiBut *ui_def_but_rna(uiBlock *block, int type, int retval, char *str, short x1, RNA_property_int_range(ptr, prop, &hardmin, &hardmax); RNA_property_int_ui_range(ptr, prop, &softmin, &softmax, &step); - if(min == max) { + if(type != ROW && min == max) { min= hardmin; max= hardmax; } @@ -2199,7 +2199,7 @@ uiBut *ui_def_but_rna(uiBlock *block, int type, int retval, char *str, short x1, RNA_property_float_range(ptr, prop, &hardmin, &hardmax); RNA_property_float_ui_range(ptr, prop, &softmin, &softmax, &step, &precision); - if(min == max) { + if(type != ROW && min == max) { min= hardmin; max= hardmax; } @@ -2919,15 +2919,15 @@ uiBut *uiDefSearchBut(uiBlock *block, void *arg, int retval, int icon, int maxle } /* arg is user value, searchfunc and handlefunc both get it as arg */ -void uiButSetSearchFunc(uiBut *but, uiButSearchFunc sfunc, void *arg, uiButHandleFunc bfunc) +/* if active set, button opens with this item visible and selected */ +void uiButSetSearchFunc(uiBut *but, uiButSearchFunc sfunc, void *arg, uiButHandleFunc bfunc, void *active) { but->search_func= sfunc; but->search_arg= arg; - uiButSetFunc(but, bfunc, arg, NULL); + uiButSetFunc(but, bfunc, arg, active); } - /* Program Init/Exit */ void UI_init(void) diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 5049fc0b130..7ad422ef3b5 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -112,6 +112,9 @@ typedef struct uiHandleButtonData { /* tooltip */ ARegion *tooltip; wmTimer *tooltiptimer; + + /* auto open */ + int used_mouse; wmTimer *autoopentimer; /* text selection/editing */ @@ -284,16 +287,6 @@ static void ui_apply_but_funcs_after(bContext *C) if(after.context) CTX_store_set(C, after.context); - if(after.func) - after.func(C, after.func_arg1, after.func_arg2); - if(after.funcN) - after.funcN(C, after.func_argN, after.func_arg2); - - if(after.handle_func) - after.handle_func(C, after.handle_func_arg, after.retval); - if(after.butm_func) - after.butm_func(C, after.butm_func_arg, after.a2); - if(after.optype) WM_operator_name_call(C, after.optype->idname, after.opcontext, after.opptr); if(after.opptr) { @@ -308,6 +301,16 @@ static void ui_apply_but_funcs_after(bContext *C) CTX_store_set(C, NULL); CTX_store_free(after.context); } + + if(after.func) + after.func(C, after.func_arg1, after.func_arg2); + if(after.funcN) + after.funcN(C, after.func_argN, after.func_arg2); + + if(after.handle_func) + after.handle_func(C, after.handle_func_arg, after.retval); + if(after.butm_func) + after.butm_func(C, after.butm_func_arg, after.a2); } } @@ -3344,7 +3347,7 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s /* automatic open pulldown block timer */ if(ELEM3(but->type, BLOCK, PULLDOWN, ICONTEXTROW)) { - if(!data->autoopentimer) { + if(data->used_mouse && !data->autoopentimer) { int time; if(but->block->auto_open==2) time= 1; // test for toolbox @@ -3447,6 +3450,9 @@ static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonA if(but->block->auto_open_last+BUTTON_AUTO_OPEN_THRESH < PIL_check_seconds_timer()) but->block->auto_open= 0; + if(type == BUTTON_ACTIVATE_OVER) { + data->used_mouse= 1; + } button_activate_state(C, but, BUTTON_STATE_HIGHLIGHT); if(type == BUTTON_ACTIVATE_OPEN) { @@ -3765,12 +3771,19 @@ static void ui_handle_button_return_submenu(bContext *C, wmEvent *event, uiBut * button_activate_exit(C, data, but, 1); } else if(menu->menuretval == UI_RETURN_OUT) { - if(ui_mouse_inside_button(data->region, but, event->x, event->y)) { + if(event->type==MOUSEMOVE && ui_mouse_inside_button(data->region, but, event->x, event->y)) { button_activate_state(C, but, BUTTON_STATE_HIGHLIGHT); } else { - data->cancel= 1; - button_activate_exit(C, data, but, 1); + but= ui_but_find_activated(data->region); + if(but) { + but->active->used_mouse= 0; + button_activate_state(C, but, BUTTON_STATE_HIGHLIGHT); + } + else { + data->cancel= 1; + button_activate_exit(C, data, but, 1); + } } } } diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index 4d8ec5996be..315b8693905 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -728,21 +728,28 @@ static void icon_create_mipmap(struct PreviewImage* prv_img, int miplevel) } /* create single icon from jpg, png etc. */ -static void icon_from_image(Image *img, int miplevel) +static void icon_from_image(Scene *scene, Image *img, int miplevel) { + ImBuf *ibuf= NULL; + ImageUser iuser; + PreviewImage *pi; unsigned int pr_size; short image_loaded = 0; - struct ImBuf* ibuf=NULL; - PreviewImage* pi; /* img->ok is zero when Image cannot load */ if (img==NULL || img->ok==0) return; + /* setup dummy image user */ + memset(&iuser, 0, sizeof(ImageUser)); + iuser.ok= iuser.framenr= 1; + iuser.scene= scene; + /* elubie: this needs to be changed: here image is always loaded if not already there. Very expensive for large images. Need to find a way to only get existing ibuf */ - ibuf = BKE_image_get_ibuf(img, NULL); + + ibuf = BKE_image_get_ibuf(img, &iuser); if(ibuf==NULL || ibuf->rect==NULL) { return; } @@ -788,7 +795,7 @@ static void icon_set_image(Scene *scene, ID *id, PreviewImage* prv_img, int mipl /* no drawing (see last parameter doDraw, just calculate preview image - hopefully small enough to be fast */ if (GS(id->name) == ID_IM) - icon_from_image((struct Image*)id, miplevel); + icon_from_image(scene, (struct Image*)id, miplevel); else { /* create the preview rect */ icon_create_mipmap(prv_img, miplevel); diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 94280ec37d3..f9816235b88 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -936,7 +936,7 @@ void ui_but_add_search(uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRN but->rnasearchprop= searchprop; but->flag |= UI_ICON_LEFT|UI_TEXT_LEFT; - uiButSetSearchFunc(but, rna_search_cb, but, NULL); + uiButSetSearchFunc(but, rna_search_cb, but, NULL, NULL); } } diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index eaf78ae89ef..a20884a61a3 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -104,6 +104,8 @@ static int panel_aligned(ScrArea *sa, ARegion *ar) SpaceButs *sbuts= sa->spacedata.first; return sbuts->align; } + else if(sa->spacetype==SPACE_FILE && ar->regiontype == RGN_TYPE_CHANNELS) + return BUT_VERTICAL; else if(ELEM(ar->regiontype, RGN_TYPE_UI, RGN_TYPE_TOOLS)) return BUT_VERTICAL; @@ -126,6 +128,8 @@ static int panels_re_align(ScrArea *sa, ARegion *ar, Panel **r_pa) } else if(ar->regiontype==RGN_TYPE_UI) return 1; + else if(sa->spacetype==SPACE_FILE && ar->regiontype == RGN_TYPE_CHANNELS) + return 1; /* in case panel is added or disappears */ for(pa=ar->panels.first; pa; pa=pa->next) { diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index 61cf612e912..27fb0731d67 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -437,6 +437,7 @@ struct uiSearchItems { int *icons; AutoComplete *autocpl; + void *active; }; typedef struct uiSearchboxData { @@ -459,6 +460,14 @@ int uiSearchItemAdd(uiSearchItems *items, const char *name, void *poin, int icon return 1; } + /* hijack for finding active item */ + if(items->active) { + if(poin==items->active) + items->offset_i= items->totitem; + items->totitem++; + return 1; + } + if(items->totitem>=items->maxitem) { items->more= 1; return 0; @@ -597,20 +606,52 @@ void ui_searchbox_update(bContext *C, ARegion *ar, uiBut *but, int reset) /* reset vars */ data->items.totitem= 0; data->items.more= 0; - if(reset==0) + if(reset==0) { data->items.offset_i= data->items.offset; + } else { data->items.offset_i= data->items.offset= 0; data->active= 0; + + /* handle active */ + if(but->search_func && but->func_arg2) { + data->items.active= but->func_arg2; + but->search_func(C, but->search_arg, but->editstr, &data->items); + data->items.active= NULL; + + /* found active item, calculate real offset by centering it */ + if(data->items.totitem) { + /* first case, begin of list */ + if(data->items.offset_i < data->items.maxitem) { + data->active= data->items.offset_i+1; + data->items.offset_i= 0; + } + else { + /* second case, end of list */ + if(data->items.totitem - data->items.offset_i <= data->items.maxitem) { + data->active= 1 + data->items.offset_i - data->items.totitem + data->items.maxitem; + data->items.offset_i= data->items.totitem - data->items.maxitem; + } + else { + /* center active item */ + data->items.offset_i -= data->items.maxitem/2; + data->active= 1 + data->items.maxitem/2; + } + } + } + data->items.offset= data->items.offset_i; + data->items.totitem= 0; + } } /* callback */ if(but->search_func) but->search_func(C, but->search_arg, but->editstr, &data->items); - if(reset) { + /* handle case where editstr is equal to one of items */ + if(reset && data->active==0) { int a; - /* handle case where editstr is equal to one of items */ + for(a=0; aitems.totitem; a++) { char *cpoin= strchr(data->items.names[a], '|'); @@ -666,13 +707,15 @@ static void ui_searchbox_region_draw(const bContext *C, ARegion *ar) } /* indicate more */ if(data->items.more) { + ui_searchbox_butrect(&rect, data, data->items.maxitem-1); glEnable(GL_BLEND); - UI_icon_draw((data->bbox.xmax-data->bbox.xmin)/2, 8, ICON_TRIA_DOWN); + UI_icon_draw((rect.xmax-rect.xmin)/2, rect.ymin-9, ICON_TRIA_DOWN); glDisable(GL_BLEND); } if(data->items.offset) { + ui_searchbox_butrect(&rect, data, 0); glEnable(GL_BLEND); - UI_icon_draw((data->bbox.xmax-data->bbox.xmin)/2, data->bbox.ymax-13, ICON_TRIA_UP); + UI_icon_draw((rect.xmax-rect.xmin)/2, rect.ymax-7, ICON_TRIA_UP); glDisable(GL_BLEND); } } @@ -2719,6 +2762,8 @@ void uiPupMenuReports(bContext *C, ReportList *reports) BLI_dynstr_appendf(ds, "Error %%i%d%%t|%s", ICON_ERROR, report->message); else if(report->type >= RPT_WARNING) BLI_dynstr_appendf(ds, "Warning %%i%d%%t|%s", ICON_ERROR, report->message); + else if(report->type >= RPT_INFO) + BLI_dynstr_appendf(ds, "Info %%t|%s", report->message); } str= BLI_dynstr_get_cstring(ds); diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index a006187c4aa..8f1d57b28ed 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -112,6 +112,7 @@ static uiBlock *search_menu(bContext *C, ARegion *ar, void *arg_litem) { static char search[256]; static TemplateID template; + PointerRNA idptr; wmEvent event; wmWindow *win= CTX_wm_window(C); uiBlock *block; @@ -122,6 +123,9 @@ static uiBlock *search_menu(bContext *C, ARegion *ar, void *arg_litem) /* arg_litem is malloced, can be freed by parent button */ template= *((TemplateID*)arg_litem); + /* get active id for showing first item */ + idptr= RNA_property_pointer_get(&template.ptr, template.prop); + block= uiBeginBlock(C, ar, "_popup", UI_EMBOSS); uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1); @@ -129,7 +133,7 @@ static uiBlock *search_menu(bContext *C, ARegion *ar, void *arg_litem) 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, &template, id_search_call_cb); + uiButSetSearchFunc(but, id_search_cb, &template, id_search_call_cb, idptr.data); uiBoundsBlock(block, 6); uiBlockSetDirection(block, UI_DOWN); @@ -157,9 +161,15 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) switch(event) { case UI_ID_BROWSE: case UI_ID_PIN: + printf("warning, id event %d shouldnt come here\n", event); + break; case UI_ID_OPEN: case UI_ID_ADD_NEW: - printf("warning, id event %d shouldnt come here\n", event); + if(template->idlb->last) { + RNA_id_pointer_create(template->idlb->last, &idptr); + RNA_property_pointer_set(&template->ptr, template->prop, idptr); + RNA_property_update(C, &template->ptr, template->prop); + } break; case UI_ID_DELETE: memset(&idptr, 0, sizeof(idptr)); @@ -197,12 +207,13 @@ static void template_ID(bContext *C, uiBlock *block, TemplateID *template, Struc idptr= RNA_property_pointer_get(&template->ptr, template->prop); lb= template->idlb; + uiBlockBeginAlign(block); + if(idptr.type) type= idptr.type; if(type) uiDefIconBut(block, LABEL, 0, RNA_struct_ui_icon(type), 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); - uiBlockBeginAlign(block); if(flag & UI_ID_BROWSE) uiDefBlockButN(block, search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X, UI_UNIT_Y, "Browse ID data"); @@ -221,6 +232,7 @@ static void template_ID(bContext *C, uiBlock *block, TemplateID *template, Struc if(newop) { but= uiDefIconTextButO(block, BUT, newop, WM_OP_EXEC_REGION_WIN, ICON_ZOOMIN, "Add 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 { but= uiDefIconTextBut(block, BUT, 0, ICON_ZOOMIN, "Add New", 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL); @@ -1474,93 +1486,63 @@ void uiTemplateLayers(uiLayout *layout, PointerRNA *ptr, char *propname) /************************* List Template **************************/ -#if 0 -typedef struct ListItem { - PointerRNA ptr; - PropertyRNA *prop; - PropertyRNA *activeprop; - - PointerRNA activeptr; - int activei; - - int selected; -} ListItem; - -static void list_item_cb(bContext *C, void *arg_item, void *arg_unused) -{ - ListItem *item= (ListItem*)arg_item; - PropertyType activetype; - char *activename; - - if(item->selected) { - activetype= RNA_property_type(item->activeprop); - - if(activetype == PROP_POINTER) - RNA_property_pointer_set(&item->ptr, item->activeprop, item->activeptr); - else if(activetype == PROP_INT) - RNA_property_int_set(&item->ptr, item->activeprop, item->activei); - else if(activetype == PROP_STRING) { - activename= RNA_struct_name_get_alloc(&item->activeptr, NULL, 0); - RNA_property_string_set(&item->ptr, item->activeprop, activename); - MEM_freeN(activename); - } - } -} -#endif - -ListBase uiTemplateList(uiLayout *layout, PointerRNA *ptr, char *propname, char *activepropname, int rows, int columns, int compact) +ListBase uiTemplateList(uiLayout *layout, PointerRNA *ptr, char *propname, PointerRNA *activeptr, char *activepropname, int rows, int columns, int compact) { CollectionPointerLink *link; - PropertyRNA *prop, *activeprop; + PropertyRNA *prop= NULL, *activeprop; PropertyType type, activetype; - PointerRNA activeptr; uiLayout *box, *row, *col; uiBlock *block; uiBut *but; + Panel *pa; ListBase lb; - char *name, *activename= NULL, str[32]; - int i= 1, activei= 0, len, items, found; - static int scroll = 1; + char *name, str[32]; + int i= 0, activei= 0, len, items, found, min, max; lb.first= lb.last= NULL; /* validate arguments */ - if(!ptr->data) - return lb; - - prop= RNA_struct_find_property(ptr, propname); - if(!prop) { - printf("uiTemplateList: property not found: %s\n", propname); + block= uiLayoutGetBlock(layout); + pa= block->panel; + + if(!pa) { + printf("uiTemplateList: only works inside a panel.\n"); return lb; } - activeprop= RNA_struct_find_property(ptr, activepropname); + if(!activeptr->data) + return lb; + + if(ptr->data) { + prop= RNA_struct_find_property(ptr, propname); + if(!prop) { + printf("uiTemplateList: property not found: %s\n", propname); + return lb; + } + } + + activeprop= RNA_struct_find_property(activeptr, activepropname); if(!activeprop) { printf("uiTemplateList: property not found: %s\n", activepropname); return lb; } - type= RNA_property_type(prop); - if(type != PROP_COLLECTION) { - printf("uiTemplateList: expected collection property.\n"); - return lb; + if(prop) { + type= RNA_property_type(prop); + if(type != PROP_COLLECTION) { + printf("uiTemplateList: expected collection property.\n"); + return lb; + } } activetype= RNA_property_type(activeprop); - if(!ELEM3(activetype, PROP_POINTER, PROP_INT, PROP_STRING)) { - printf("uiTemplateList: expected pointer, integer or string property.\n"); + if(activetype != PROP_INT) { + printf("uiTemplateList: expected integer property.\n"); return lb; } /* get active data */ - if(activetype == PROP_POINTER) - activeptr= RNA_property_pointer_get(ptr, activeprop); - else if(activetype == PROP_INT) - activei= RNA_property_int_get(ptr, activeprop); - else if(activetype == PROP_STRING) - activename= RNA_property_string_get_alloc(ptr, activeprop, NULL, 0); - - block= uiLayoutGetBlock(layout); + activei= RNA_property_int_get(activeptr, activeprop); if(compact) { /* compact layout */ @@ -1568,111 +1550,196 @@ ListBase uiTemplateList(uiLayout *layout, PointerRNA *ptr, char *propname, char row= uiLayoutRow(layout, 1); - RNA_PROP_BEGIN(ptr, itemptr, prop) { - if(activetype == PROP_POINTER) - found= (activeptr.data == itemptr.data); - else if(activetype == PROP_INT) + if(ptr->data && prop) { + /* create list items */ + RNA_PROP_BEGIN(ptr, itemptr, prop) { found= (activei == i); - else if(activetype == PROP_STRING) - found= (strcmp(activename, name) == 0); - if(found) { - name= RNA_struct_name_get_alloc(&itemptr, NULL, 0); - if(name) { - uiItemL(row, name, RNA_struct_ui_icon(itemptr.type)); - MEM_freeN(name); + if(found) { + /* create button */ + name= RNA_struct_name_get_alloc(&itemptr, NULL, 0); + if(name) { + uiItemL(row, name, RNA_struct_ui_icon(itemptr.type)); + MEM_freeN(name); + } + + /* add to list to return */ + link= MEM_callocN(sizeof(CollectionPointerLink), "uiTemplateList return"); + link->ptr= itemptr; + BLI_addtail(&lb, link); } - link= MEM_callocN(sizeof(CollectionPointerLink), "uiTemplateList return"); - link->ptr= itemptr; - BLI_addtail(&lb, link); + i++; } - - i++; + RNA_PROP_END; } - RNA_PROP_END; - if(i == 1) + /* if not found, add in dummy button */ + if(i == 0) uiItemL(row, "", 0); - sprintf(str, "%d :", i-1); - but= uiDefIconTextButR(block, NUM, 0, 0, str, 0,0,UI_UNIT_X*5,UI_UNIT_Y, ptr, activepropname, 0, 0, 0, 0, 0, ""); - if(i == 1) + /* next/prev button */ + sprintf(str, "%d :", i); + but= uiDefIconTextButR(block, NUM, 0, 0, str, 0,0,UI_UNIT_X*5,UI_UNIT_Y, activeptr, activepropname, 0, 0, 0, 0, 0, ""); + if(i == 0) uiButSetFlag(but, UI_BUT_DISABLED); } else { + /* default rows/columns */ if(rows == 0) rows= 5; if(columns == 0) columns= 1; - items= rows*columns; - + /* layout */ box= uiLayoutBox(layout); row= uiLayoutRow(box, 0); col = uiLayoutColumn(row, 1); uiBlockSetEmboss(block, UI_EMBOSSN); - len= RNA_property_collection_length(ptr, prop); - scroll= MIN2(scroll, len-items+1); - scroll= MAX2(scroll, 1); + /* init numbers */ + RNA_property_int_range(activeptr, activeprop, &min, &max); - RNA_PROP_BEGIN(ptr, itemptr, prop) { - if(i >= scroll && ilist_scroll= MIN2(pa->list_scroll, len-items); + pa->list_scroll= MAX2(pa->list_scroll, 0); - item->ptr= *ptr; - item->prop= prop; - item->activeprop= activeprop; - item->activeptr= itemptr; - item->activei= i; + if(ptr->data && prop) { + /* create list items */ + RNA_PROP_BEGIN(ptr, itemptr, prop) { + if(i >= pa->list_scroll && ilist_scroll+items) { + name= RNA_struct_name_get_alloc(&itemptr, NULL, 0); - if(activetype == PROP_POINTER) - item->selected= (activeptr.data == itemptr.data)? i: -1; - else if(activetype == PROP_INT) - item->selected= (activei == i)? i: -1; - else if(activetype == PROP_STRING) - item->selected= (strcmp(activename, name) == 0)? i: -1; -#endif + if(name) { + /* create button */ + but= uiDefIconTextButR(block, ROW, 0, RNA_struct_ui_icon(itemptr.type), name, 0,0,UI_UNIT_X*10,UI_UNIT_Y, activeptr, activepropname, 0, 0, i, 0, 0, ""); + uiButSetFlag(but, UI_ICON_LEFT|UI_TEXT_LEFT); - //but= uiDefIconTextButI(block, ROW, 0, RNA_struct_ui_icon(itemptr.type), name, 0,0,UI_UNIT_X*10,UI_UNIT_Y, &item->selected, 0, i, 0, 0, ""); - but= uiDefIconTextButR(block, ROW, 0, RNA_struct_ui_icon(itemptr.type), name, 0,0,UI_UNIT_X*10,UI_UNIT_Y, ptr, activepropname, 0/*&item->selected*/, 0, i, 0, 0, ""); - uiButSetFlag(but, UI_ICON_LEFT|UI_TEXT_LEFT); - //uiButSetNFunc(but, list_item_cb, item, NULL); - - MEM_freeN(name); + MEM_freeN(name); + } + /* add to list to return */ link= MEM_callocN(sizeof(CollectionPointerLink), "uiTemplateList return"); link->ptr= itemptr; BLI_addtail(&lb, link); } + + i++; } - - i++; + RNA_PROP_END; } - RNA_PROP_END; - while(i < scroll+items) { - if(i >= scroll) + /* add dummy buttons to fill space */ + while(i < pa->list_scroll+items) { + if(i >= pa->list_scroll) uiItemL(col, "", 0); i++; } uiBlockSetEmboss(block, UI_EMBOSS); + /* add scrollbar */ if(len > items) { col= uiLayoutColumn(row, 0); - uiDefButI(block, SCROLL, 0, "", 0,0,UI_UNIT_X*0.75,UI_UNIT_Y*items, &scroll, 1, len-items+1, items, 0, ""); + uiDefButI(block, SCROLL, 0, "", 0,0,UI_UNIT_X*0.75,UI_UNIT_Y*items, &pa->list_scroll, 0, len-items, items, 0, ""); } - - //uiDefButI(block, SCROLL, 0, "", 0,0,UI_UNIT_X*15,UI_UNIT_Y*0.75, &scroll, 1, 16-5, 5, 0, ""); } + /* return items in list */ return lb; } +/************************* Operator Search Template **************************/ + +static void operator_call_cb(struct bContext *C, void *arg1, void *arg2) +{ + wmOperatorType *ot= arg2; + + if(ot) + 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) +{ + wmOperatorType *ot = WM_operatortype_first(); + + for(; ot; ot= ot->next) { + + if(BLI_strcasestr(ot->name, str)) { + if(ot->poll==NULL || ot->poll((bContext *)C)) { + char name[256]; + int len= strlen(ot->name); + + /* display name for menu, can hold hotkey */ + BLI_strncpy(name, ot->name, 256); + + /* check for hotkey */ + if(len < 256-6) { + if(WM_key_event_operator_string(C, ot->idname, WM_OP_EXEC_DEFAULT, NULL, &name[len+1], 256-len-1)) + name[len]= '|'; + } + + if(0==uiSearchItemAdd(items, name, ot, 0)) + break; + } + } + } +} + +void uiTemplateOperatorSearch(uiLayout *layout) +{ + uiBlock *block; + uiBut *but; + static char search[256]= ""; + + block= uiLayoutGetBlock(layout); + uiBlockSetCurLayout(block, layout); + + but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 0, 0, UI_UNIT_X*6, UI_UNIT_Y, ""); + uiButSetSearchFunc(but, operator_search_cb, NULL, operator_call_cb, NULL); +} + +/************************* Running Jobs Template **************************/ + +#define B_STOPRENDER 1 +#define B_STOPCAST 2 +#define B_STOPANIM 3 + +static void do_running_jobs(bContext *C, void *arg, int event) +{ + switch(event) { + case B_STOPRENDER: + G.afbreek= 1; + break; + case B_STOPCAST: + WM_jobs_stop(CTX_wm_manager(C), CTX_wm_screen(C)); + break; + case B_STOPANIM: + ED_screen_animation_timer(C, 0, 0); + break; + } +} + +void uiTemplateRunningJobs(uiLayout *layout, bContext *C) +{ + bScreen *screen= CTX_wm_screen(C); + Scene *scene= CTX_data_scene(C); + wmWindowManager *wm= CTX_wm_manager(C); + uiBlock *block; + + block= uiLayoutGetBlock(layout); + uiBlockSetCurLayout(block, layout); + + uiBlockSetHandleFunc(block, do_running_jobs, NULL); + + if(WM_jobs_test(wm, scene)) + uiDefIconTextBut(block, BUT, B_STOPRENDER, ICON_REC, "Render", 0,0,75,UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "Stop rendering"); + if(WM_jobs_test(wm, screen)) + uiDefIconTextBut(block, BUT, B_STOPCAST, ICON_REC, "Capture", 0,0,85,UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "Stop screencast"); + if(screen->animtimer) + 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"); +} + diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c index 3ed81a3e9bc..eb79848d7d2 100644 --- a/source/blender/editors/interface/interface_utils.c +++ b/source/blender/editors/interface/interface_utils.c @@ -327,7 +327,7 @@ static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_params) 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); + uiButSetSearchFunc(but, id_search_cb, ¶ms, id_search_call_cb, NULL); uiBoundsBlock(block, 6); uiBlockSetDirection(block, UI_DOWN); diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index ddf31c0db66..ed2d00cb00d 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -1679,12 +1679,12 @@ static void widget_scroll(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat rect1= *rect; if(horizontal) { - fac= (rect->xmax - rect->xmin)/(size-1); + fac= (rect->xmax - rect->xmin)/(size); rect1.xmin= rect1.xmin + ceil(fac*(value - but->softmin)); rect1.xmax= rect1.xmin + ceil(fac*(but->a1 - but->softmin)); } else { - fac= (rect->ymax - rect->ymin)/(size-1); + fac= (rect->ymax - rect->ymin)/(size); rect1.ymax= rect1.ymax - ceil(fac*(value - but->softmin)); rect1.ymin= rect1.ymax - ceil(fac*(but->a1 - but->softmin)); } diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h index 83a4211dda1..22e3b4060a4 100644 --- a/source/blender/editors/mesh/mesh_intern.h +++ b/source/blender/editors/mesh/mesh_intern.h @@ -234,5 +234,14 @@ void MESH_OT_colors_mirror(struct wmOperatorType *ot); void MESH_OT_delete(struct wmOperatorType *ot); void MESH_OT_rip(struct wmOperatorType *ot); +/* ******************* mesh_layers.c */ + +void MESH_OT_uv_texture_add(struct wmOperatorType *ot); +void MESH_OT_uv_texture_remove(struct wmOperatorType *ot); +void MESH_OT_vertex_color_add(struct wmOperatorType *ot); +void MESH_OT_vertex_color_remove(struct wmOperatorType *ot); +void MESH_OT_sticky_add(struct wmOperatorType *ot); +void MESH_OT_sticky_remove(struct wmOperatorType *ot); + #endif // MESH_INTERN_H diff --git a/source/blender/editors/mesh/mesh_layers.c b/source/blender/editors/mesh/mesh_layers.c new file mode 100644 index 00000000000..99d50d1a9b0 --- /dev/null +++ b/source/blender/editors/mesh/mesh_layers.c @@ -0,0 +1,424 @@ +/** + * $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 +#include + +#include "MEM_guardedalloc.h" + +#include "DNA_customdata_types.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_windowmanager_types.h" + +#include "BKE_context.h" +#include "BKE_customdata.h" +#include "BKE_depsgraph.h" +#include "BKE_displist.h" +#include "BKE_global.h" +#include "BKE_mesh.h" + +#include "BLI_editVert.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_mesh.h" +#include "ED_view3d.h" + +#include "mesh_intern.h" + +static void delete_customdata_layer(Mesh *me, CustomDataLayer *layer) +{ + CustomData *data= (me->edit_mesh)? &me->edit_mesh->fdata: &me->fdata; + void *actlayerdata, *rndlayerdata, *clonelayerdata, *masklayerdata, *layerdata=layer->data; + int type= layer->type; + int index= CustomData_get_layer_index(data, type); + int i, actindex, rndindex, cloneindex, maskindex; + + /* ok, deleting a non-active layer needs to preserve the active layer indices. + to do this, we store a pointer to the .data member of both layer and the active layer, + (to detect if we're deleting the active layer or not), then use the active + layer data pointer to find where the active layer has ended up. + + this is necassary because the deletion functions only support deleting the active + layer. */ + actlayerdata = data->layers[CustomData_get_active_layer_index(data, type)].data; + rndlayerdata = data->layers[CustomData_get_render_layer_index(data, type)].data; + clonelayerdata = data->layers[CustomData_get_clone_layer_index(data, type)].data; + masklayerdata = data->layers[CustomData_get_mask_layer_index(data, type)].data; + CustomData_set_layer_active(data, type, layer - &data->layers[index]); + + if(me->edit_mesh) { + EM_free_data_layer(me->edit_mesh, data, type); + } + else { + CustomData_free_layer_active(data, type, me->totface); + mesh_update_customdata_pointers(me); + } + + if(!CustomData_has_layer(data, type)) + if(type == CD_MCOL && (G.f & G_VERTEXPAINT)) + G.f &= ~G_VERTEXPAINT; /* get out of vertexpaint mode */ + + /* reconstruct active layer */ + if (actlayerdata != layerdata) { + /* find index */ + actindex = CustomData_get_layer_index(data, type); + for (i=actindex; itotlayer; i++) { + if (data->layers[i].data == actlayerdata) { + actindex = i - actindex; + break; + } + } + + /* set index */ + CustomData_set_layer_active(data, type, actindex); + } + + if (rndlayerdata != layerdata) { + /* find index */ + rndindex = CustomData_get_layer_index(data, type); + for (i=rndindex; itotlayer; i++) { + if (data->layers[i].data == rndlayerdata) { + rndindex = i - rndindex; + break; + } + } + + /* set index */ + CustomData_set_layer_render(data, type, rndindex); + } + + if (clonelayerdata != layerdata) { + /* find index */ + cloneindex = CustomData_get_layer_index(data, type); + for (i=cloneindex; itotlayer; i++) { + if (data->layers[i].data == clonelayerdata) { + cloneindex = i - cloneindex; + break; + } + } + + /* set index */ + CustomData_set_layer_clone(data, type, cloneindex); + } + + if (masklayerdata != layerdata) { + /* find index */ + maskindex = CustomData_get_layer_index(data, type); + for (i=maskindex; itotlayer; i++) { + if (data->layers[i].data == masklayerdata) { + maskindex = i - maskindex; + break; + } + } + + /* set index */ + CustomData_set_layer_mask(data, type, maskindex); + } +} + +/*********************** UV texture operators ************************/ + +static int uv_texture_add_exec(bContext *C, wmOperator *op) +{ + Scene *scene= CTX_data_scene(C); + Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; + Mesh *me; + EditMesh *em; + int layernum; + + if(!ob || ob->type!=OB_MESH) + return OPERATOR_CANCELLED; + + me= (Mesh*)ob->data; + + if(scene->obedit == ob) { + em= me->edit_mesh; + + layernum= CustomData_number_of_layers(&em->fdata, CD_MTFACE); + if(layernum >= MAX_MTFACE) + return OPERATOR_CANCELLED; + + EM_add_data_layer(em, &em->fdata, CD_MTFACE); + CustomData_set_layer_active(&em->fdata, CD_MTFACE, layernum); + } + else if(ob) { + layernum= CustomData_number_of_layers(&me->fdata, CD_MTFACE); + if(layernum >= MAX_MTFACE) + return OPERATOR_CANCELLED; + + if(me->mtface) + CustomData_add_layer(&me->fdata, CD_MTFACE, CD_DUPLICATE, me->mtface, me->totface); + else + CustomData_add_layer(&me->fdata, CD_MTFACE, CD_DEFAULT, NULL, me->totface); + + CustomData_set_layer_active(&me->fdata, CD_MTFACE, layernum); + mesh_update_customdata_pointers(me); + } + + DAG_object_flush_update(scene, ob, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob); + + return OPERATOR_FINISHED; +} + +void MESH_OT_uv_texture_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Add UV Texture"; + ot->idname= "MESH_OT_uv_texture_add"; + + /* api callbacks */ + ot->exec= uv_texture_add_exec; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +static int uv_texture_remove_exec(bContext *C, wmOperator *op) +{ + Scene *scene= CTX_data_scene(C); + Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; + Mesh *me; + CustomDataLayer *cdl; + int index; + + if(!ob || ob->type!=OB_MESH) + return OPERATOR_CANCELLED; + + me= (Mesh*)ob->data; + index= CustomData_get_active_layer_index(&me->fdata, CD_MTFACE); + cdl= (index == -1)? NULL: &me->fdata.layers[index]; + + if(!cdl) + return OPERATOR_CANCELLED; + + delete_customdata_layer(me, cdl); + + DAG_object_flush_update(scene, ob, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob); + + return OPERATOR_FINISHED; +} + +void MESH_OT_uv_texture_remove(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Remove UV Texture"; + ot->idname= "MESH_OT_uv_texture_remove"; + + /* api callbacks */ + ot->exec= uv_texture_remove_exec; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +/*********************** vertex color operators ************************/ + +static int vertex_color_add_exec(bContext *C, wmOperator *op) +{ + Scene *scene= CTX_data_scene(C); + Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; + Mesh *me; + EditMesh *em; + MCol *mcol; + int layernum; + + if(!ob || ob->type!=OB_MESH) + return OPERATOR_CANCELLED; + + me= (Mesh*)ob->data; + + if(scene->obedit == ob) { + em= me->edit_mesh; + + layernum= CustomData_number_of_layers(&em->fdata, CD_MCOL); + if(layernum >= MAX_MCOL) + return OPERATOR_CANCELLED; + + EM_add_data_layer(em, &em->fdata, CD_MCOL); + CustomData_set_layer_active(&em->fdata, CD_MCOL, layernum); + } + else { + layernum= CustomData_number_of_layers(&me->fdata, CD_MCOL); + if(layernum >= MAX_MCOL) + return OPERATOR_CANCELLED; + + mcol= me->mcol; + + if(me->mcol) + CustomData_add_layer(&me->fdata, CD_MCOL, CD_DUPLICATE, me->mcol, me->totface); + else + CustomData_add_layer(&me->fdata, CD_MCOL, CD_DEFAULT, NULL, me->totface); + + CustomData_set_layer_active(&me->fdata, CD_MCOL, layernum); + mesh_update_customdata_pointers(me); + + if(!mcol) + shadeMeshMCol(scene, ob, me); + } + + DAG_object_flush_update(scene, ob, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob); + + return OPERATOR_FINISHED; +} + +void MESH_OT_vertex_color_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Add Vertex Color"; + ot->idname= "MESH_OT_vertex_color_add"; + + /* api callbacks */ + ot->exec= vertex_color_add_exec; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +static int vertex_color_remove_exec(bContext *C, wmOperator *op) +{ + Scene *scene= CTX_data_scene(C); + Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; + Mesh *me; + CustomDataLayer *cdl; + int index; + + if(!ob || ob->type!=OB_MESH) + return OPERATOR_CANCELLED; + + me= (Mesh*)ob->data; + index= CustomData_get_active_layer_index(&me->fdata, CD_MCOL); + cdl= (index == -1)? NULL: &me->fdata.layers[index]; + + if(!cdl) + return OPERATOR_CANCELLED; + + delete_customdata_layer(me, cdl); + + DAG_object_flush_update(scene, ob, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob); + + return OPERATOR_FINISHED; +} + +void MESH_OT_vertex_color_remove(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Remove Vertex Color"; + ot->idname= "MESH_OT_vertex_color_remove"; + + /* api callbacks */ + ot->exec= vertex_color_remove_exec; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +/*********************** sticky operators ************************/ + +static int sticky_add_exec(bContext *C, wmOperator *op) +{ + Scene *scene= CTX_data_scene(C); + Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; + Mesh *me; + + if(!ob || ob->type!=OB_MESH) + return OPERATOR_CANCELLED; + + me= (Mesh*)ob->data; + + if(me->msticky) + return OPERATOR_CANCELLED; + + // XXX RE_make_sticky(); + + DAG_object_flush_update(scene, ob, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob); + + return OPERATOR_FINISHED; +} + +void MESH_OT_sticky_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Add Sticky"; + ot->idname= "MESH_OT_sticky_add"; + + /* api callbacks */ + ot->exec= sticky_add_exec; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +static int sticky_remove_exec(bContext *C, wmOperator *op) +{ + Scene *scene= CTX_data_scene(C); + Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; + Mesh *me; + + if(!ob || ob->type!=OB_MESH) + return OPERATOR_CANCELLED; + + me= (Mesh*)ob->data; + + if(!me->msticky) + return OPERATOR_CANCELLED; + + CustomData_free_layer_active(&me->vdata, CD_MSTICKY, me->totvert); + me->msticky= NULL; + + DAG_object_flush_update(scene, ob, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob); + + return OPERATOR_FINISHED; +} + +void MESH_OT_sticky_remove(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Remove Sticky"; + ot->idname= "MESH_OT_sticky_remove"; + + /* api callbacks */ + ot->exec= sticky_remove_exec; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index 5a86180a60f..2a9357ed0f0 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -183,6 +183,12 @@ void ED_operatortypes_mesh(void) WM_operatortype_append(MESH_OT_knife_cut); WM_operatortype_append(MESH_OT_rip); + WM_operatortype_append(MESH_OT_uv_texture_add); + WM_operatortype_append(MESH_OT_uv_texture_remove); + WM_operatortype_append(MESH_OT_vertex_color_add); + WM_operatortype_append(MESH_OT_vertex_color_remove); + WM_operatortype_append(MESH_OT_sticky_add); + WM_operatortype_append(MESH_OT_sticky_remove); } /* note mesh keymap also for other space? */ diff --git a/source/blender/editors/object/editkey.c b/source/blender/editors/object/editkey.c index 913046c5ab8..1c31c7c7653 100644 --- a/source/blender/editors/object/editkey.c +++ b/source/blender/editors/object/editkey.c @@ -55,6 +55,7 @@ #include "BKE_action.h" #include "BKE_anim.h" +#include "BKE_context.h" #include "BKE_curve.h" #include "BKE_depsgraph.h" #include "BKE_global.h" @@ -70,11 +71,15 @@ #include "ED_object.h" +#include "RNA_access.h" + +#include "WM_api.h" +#include "WM_types.h" + #include "object_intern.h" /* XXX */ static void BIF_undo_push() {} -static void error() {} /* XXX */ #if 0 // XXX old animation system @@ -394,25 +399,6 @@ void insert_curvekey(Scene *scene, Curve *cu, short rel) /* ******************** */ -void insert_shapekey(Scene *scene, Object *ob) -{ - if(get_mesh(ob) && get_mesh(ob)->mr) { - error("Cannot create shape keys on a multires mesh."); - } - else { - Key *key; - - if(ob->type==OB_MESH) insert_meshkey(scene, ob->data, 1); - else if ELEM(ob->type, OB_CURVE, OB_SURF) insert_curvekey(scene, ob->data, 1); - else if(ob->type==OB_LATTICE) insert_lattkey(scene, ob->data, 1); - - key= ob_get_key(ob); - ob->shapenr= BLI_countlist(&key->block); - - BIF_undo_push("Add Shapekey"); - } -} - void delete_key(Scene *scene, Object *ob) { KeyBlock *kb, *rkb; @@ -473,6 +459,123 @@ void delete_key(Scene *scene, Object *ob) BIF_undo_push("Delete Shapekey"); } +/********************** shape key operators *********************/ + +static int shape_key_add_exec(bContext *C, wmOperator *op) +{ + Scene *scene= CTX_data_scene(C); + Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; + Key *key; + + if(!ob) + return OPERATOR_CANCELLED; + + if(ob->type==OB_MESH) insert_meshkey(scene, ob->data, 1); + else if ELEM(ob->type, OB_CURVE, OB_SURF) insert_curvekey(scene, ob->data, 1); + else if(ob->type==OB_LATTICE) insert_lattkey(scene, ob->data, 1); + + key= ob_get_key(ob); + ob->shapenr= BLI_countlist(&key->block); + + WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); + + return OPERATOR_FINISHED; +} + +void OBJECT_OT_shape_key_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Add Shape Key"; + ot->idname= "OBJECT_OT_shape_key_add"; + + /* api callbacks */ + ot->exec= shape_key_add_exec; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +static int shape_key_remove_exec(bContext *C, wmOperator *op) +{ + Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; + Scene *scene= CTX_data_scene(C); + Main *bmain= CTX_data_main(C); + KeyBlock *kb, *rkb; + Key *key; + //IpoCurve *icu; + + if(!ob) + return OPERATOR_CANCELLED; + + key= ob_get_key(ob); + if(key==NULL) + return OPERATOR_CANCELLED; + + kb= BLI_findlink(&key->block, ob->shapenr-1); + + if(kb) { + for(rkb= key->block.first; rkb; rkb= rkb->next) + if(rkb->relative == ob->shapenr-1) + rkb->relative= 0; + + BLI_remlink(&key->block, kb); + key->totkey--; + if(key->refkey== kb) + key->refkey= key->block.first; + + if(kb->data) MEM_freeN(kb->data); + MEM_freeN(kb); + + for(kb= key->block.first; kb; kb= kb->next) + if(kb->adrcode>=ob->shapenr) + kb->adrcode--; + +#if 0 // XXX old animation system + if(key->ipo) { + + for(icu= key->ipo->curve.first; icu; icu= icu->next) { + if(icu->adrcode==ob->shapenr-1) { + BLI_remlink(&key->ipo->curve, icu); + free_ipo_curve(icu); + break; + } + } + for(icu= key->ipo->curve.first; icu; icu= icu->next) + if(icu->adrcode>=ob->shapenr) + icu->adrcode--; + } +#endif // XXX old animation system + + if(ob->shapenr>1) ob->shapenr--; + } + + if(key->totkey==0) { + if(GS(key->from->name)==ID_ME) ((Mesh *)key->from)->key= NULL; + else if(GS(key->from->name)==ID_CU) ((Curve *)key->from)->key= NULL; + else if(GS(key->from->name)==ID_LT) ((Lattice *)key->from)->key= NULL; + + free_libblock_us(&(bmain->key), key); + } + + DAG_object_flush_update(scene, OBACT, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); + + return OPERATOR_FINISHED; +} + +void OBJECT_OT_shape_key_remove(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Remove Shape Key"; + ot->idname= "OBJECT_OT_shape_key_remove"; + + /* api callbacks */ + ot->exec= shape_key_remove_exec; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + void move_keys(Object *ob) { #if 0 @@ -560,3 +663,4 @@ void move_keys(Object *ob) BIF_undo_push("Move Shapekey(s)"); #endif } + diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index 1eb867e19a0..a52acdd4e1e 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -92,5 +92,19 @@ void OBJECT_OT_modifier_mdef_bind(struct wmOperatorType *ot); /* editconstraint.c */ void OBJECT_OT_constraint_add(struct wmOperatorType *ot); +/* object_vgroup.c */ +void OBJECT_OT_vertex_group_add(struct wmOperatorType *ot); +void OBJECT_OT_vertex_group_remove(struct wmOperatorType *ot); +void OBJECT_OT_vertex_group_assign(struct wmOperatorType *ot); +void OBJECT_OT_vertex_group_remove_from(struct wmOperatorType *ot); +void OBJECT_OT_vertex_group_select(struct wmOperatorType *ot); +void OBJECT_OT_vertex_group_deselect(struct wmOperatorType *ot); +void OBJECT_OT_vertex_group_copy_to_linked(struct wmOperatorType *ot); +void OBJECT_OT_vertex_group_copy(struct wmOperatorType *ot); + +/* editkey.c */ +void OBJECT_OT_shape_key_add(struct wmOperatorType *ot); +void OBJECT_OT_shape_key_remove(struct wmOperatorType *ot); + #endif /* ED_OBJECT_INTERN_H */ diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index cfee6a55152..6fa78a53840 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -104,6 +104,18 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_modifier_mdef_bind); WM_operatortype_append(OBJECT_OT_constraint_add); + + WM_operatortype_append(OBJECT_OT_vertex_group_add); + WM_operatortype_append(OBJECT_OT_vertex_group_remove); + WM_operatortype_append(OBJECT_OT_vertex_group_assign); + WM_operatortype_append(OBJECT_OT_vertex_group_remove_from); + WM_operatortype_append(OBJECT_OT_vertex_group_select); + WM_operatortype_append(OBJECT_OT_vertex_group_deselect); + WM_operatortype_append(OBJECT_OT_vertex_group_copy_to_linked); + WM_operatortype_append(OBJECT_OT_vertex_group_copy); + + WM_operatortype_append(OBJECT_OT_shape_key_add); + WM_operatortype_append(OBJECT_OT_shape_key_remove); } void ED_keymap_object(wmWindowManager *wm) diff --git a/source/blender/editors/mesh/editdeform.c b/source/blender/editors/object/object_vgroup.c similarity index 80% rename from source/blender/editors/mesh/editdeform.c rename to source/blender/editors/object/object_vgroup.c index 3ccd4d56ece..fb71fc09108 100644 --- a/source/blender/editors/mesh/editdeform.c +++ b/source/blender/editors/object/object_vgroup.c @@ -48,19 +48,26 @@ #include "BLI_blenlib.h" #include "BLI_editVert.h" +#include "BKE_context.h" #include "BKE_customdata.h" -#include "BKE_DerivedMesh.h" -#include "BKE_depsgraph.h" #include "BKE_deform.h" +#include "BKE_depsgraph.h" +#include "BKE_DerivedMesh.h" #include "BKE_displist.h" #include "BKE_global.h" #include "BKE_lattice.h" #include "BKE_mesh.h" #include "BKE_utildefines.h" +#include "RNA_access.h" + +#include "WM_api.h" +#include "WM_types.h" + #include "ED_mesh.h" #include "ED_view3d.h" -#include "mesh_intern.h" + +#include "object_intern.h" /* XXX */ static void BIF_undo_push() {} @@ -719,18 +726,13 @@ void add_vert_to_defgroup (Object *ob, bDeformGroup *dg, int vertnum, } /* Only available in editmode */ -void assign_verts_defgroup (Object *obedit, float weight) +void assign_verts_defgroup (Object *ob, float weight) { - Object *ob; EditVert *eve; bDeformGroup *dg, *eg; MDeformWeight *newdw; MDeformVert *dvert; int i, done; - -// XXX if(multires_level1_test()) return; - - ob= obedit; if (!ob) return; @@ -883,18 +885,13 @@ float get_vert_defgroup (Object *ob, bDeformGroup *dg, int vertnum) /* Only available in editmode */ /* removes from active defgroup, if allverts==0 only selected vertices */ -void remove_verts_defgroup (Object *obedit, int allverts) +void remove_verts_defgroup (Object *ob, int allverts) { - Object *ob; EditVert *eve; MDeformVert *dvert; MDeformWeight *newdw; bDeformGroup *dg, *eg; int i; - -// XXX if(multires_level1_test()) return; - - ob= obedit; if (!ob) return; @@ -966,14 +963,10 @@ void remove_verts_defgroup (Object *obedit, int allverts) /* Only available in editmode */ /* removes from all defgroup, if allverts==0 only selected vertices */ -void remove_verts_defgroups(Object *obedit, int allverts) +void remove_verts_defgroups(Object *ob, int allverts) { - Object *ob; int actdef, defCount; - -// XXX if (multires_level1_test()) return; - ob= obedit; if (ob == NULL) return; actdef= ob->actdef; @@ -1107,4 +1100,245 @@ void vgroup_operation_with_menu(Object *ob) } } +/********************** vertex group operators *********************/ + +static int vertex_group_add_exec(bContext *C, wmOperator *op) +{ + Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; + Scene *scene= CTX_data_scene(C); + + if(!ob) + return OPERATOR_CANCELLED; + + add_defgroup(ob); + DAG_object_flush_update(scene, ob, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob); + + return OPERATOR_FINISHED; +} + +void OBJECT_OT_vertex_group_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Add Vertex Group"; + ot->idname= "OBJECT_OT_vertex_group_add"; + + /* api callbacks */ + ot->exec= vertex_group_add_exec; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +static int vertex_group_remove_exec(bContext *C, wmOperator *op) +{ + Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; + Scene *scene= CTX_data_scene(C); + + if(!ob) + return OPERATOR_CANCELLED; + + if(scene->obedit == ob) { + del_defgroup(ob); + WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob); + } + else { + del_defgroup_in_object_mode(ob); + DAG_object_flush_update(scene, ob, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob); + } + + return OPERATOR_FINISHED; +} + +void OBJECT_OT_vertex_group_remove(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Remove Vertex Group"; + ot->idname= "OBJECT_OT_vertex_group_remove"; + + /* api callbacks */ + ot->exec= vertex_group_remove_exec; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +static int vertex_group_assign_exec(bContext *C, wmOperator *op) +{ + Scene *scene= CTX_data_scene(C); + ToolSettings *ts= CTX_data_tool_settings(C); + Object *ob= CTX_data_edit_object(C); + + if(!ob) + return OPERATOR_CANCELLED; + + assign_verts_defgroup(ob, ts->vgroup_weight); + DAG_object_flush_update(scene, ob, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob); + + return OPERATOR_FINISHED; +} + +void OBJECT_OT_vertex_group_assign(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Assign Vertex Group"; + ot->idname= "OBJECT_OT_vertex_group_assign"; + + /* api callbacks */ + ot->exec= vertex_group_assign_exec; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +static int vertex_group_remove_from_exec(bContext *C, wmOperator *op) +{ + Scene *scene= CTX_data_scene(C); + Object *ob= CTX_data_edit_object(C); + + if(!ob) + return OPERATOR_CANCELLED; + + remove_verts_defgroup(ob, 0); + DAG_object_flush_update(scene, ob, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob); + + return OPERATOR_FINISHED; +} + +void OBJECT_OT_vertex_group_remove_from(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Remove from Vertex Group"; + ot->idname= "OBJECT_OT_vertex_group_remove_from"; + + /* api callbacks */ + ot->exec= vertex_group_remove_from_exec; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +static int vertex_group_select_exec(bContext *C, wmOperator *op) +{ + Object *ob= CTX_data_edit_object(C); + + if(!ob) + return OPERATOR_CANCELLED; + + sel_verts_defgroup(ob, 1); /* runs countall() */ + WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, ob); + + return OPERATOR_FINISHED; +} + +void OBJECT_OT_vertex_group_select(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Select Vertex Group"; + ot->idname= "OBJECT_OT_vertex_group_select"; + + /* api callbacks */ + ot->exec= vertex_group_select_exec; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +static int vertex_group_deselect_exec(bContext *C, wmOperator *op) +{ + Object *ob= CTX_data_edit_object(C); + + if(!ob) + return OPERATOR_CANCELLED; + + sel_verts_defgroup(ob, 0); /* runs countall() */ + WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, ob); + + return OPERATOR_FINISHED; +} + +void OBJECT_OT_vertex_group_deselect(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Deselect Vertex Group"; + ot->idname= "OBJECT_OT_vertex_group_deselect"; + + /* api callbacks */ + ot->exec= vertex_group_deselect_exec; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +static int vertex_group_copy_exec(bContext *C, wmOperator *op) +{ + Scene *scene= CTX_data_scene(C); + Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; + + if(!ob) + return OPERATOR_CANCELLED; + + duplicate_defgroup(ob); + DAG_object_flush_update(scene, ob, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob); + + return OPERATOR_FINISHED; +} + +void OBJECT_OT_vertex_group_copy(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Copy Vertex Group"; + ot->idname= "OBJECT_OT_vertex_group_copy"; + + /* api callbacks */ + ot->exec= vertex_group_copy_exec; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +static int vertex_group_copy_to_linked_exec(bContext *C, wmOperator *op) +{ + Scene *scene= CTX_data_scene(C); + Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; + Base *base; + int retval= OPERATOR_CANCELLED; + + if(!ob) + return retval; + + for(base=scene->base.first; base; base= base->next) { + if(base->object->type==ob->type) { + if(base->object!=ob && base->object->data==ob->data) { + BLI_freelistN(&base->object->defbase); + BLI_duplicatelist(&base->object->defbase, &ob->defbase); + base->object->actdef= ob->actdef; + + DAG_object_flush_update(scene, base->object, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, base->object); + + retval = OPERATOR_FINISHED; + } + } + } + + return retval; +} + +void OBJECT_OT_vertex_group_copy_to_linked(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Copy Vertex Group to Linked"; + ot->idname= "OBJECT_OT_vertex_group_copy_to_linked"; + + /* api callbacks */ + ot->exec= vertex_group_copy_to_linked_exec; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 14121ccdc4d..5bf090e459b 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -59,6 +59,7 @@ #include "ED_util.h" #include "ED_screen.h" #include "ED_mesh.h" +#include "ED_object.h" #include "ED_screen_types.h" #include "RE_pipeline.h" @@ -2515,7 +2516,9 @@ static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event) /* flush multires changes (for sculpt) */ multires_force_update(CTX_data_active_object(C)); - // get editmode results + /* get editmode results */ + ED_object_exit_editmode(C, 0); /* 0 = does not exit editmode */ + // store spare // get view3d layer, local layer, make this nice api call to render // store spare diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 8f0b52ef3a1..a2b883eabfc 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -156,7 +156,6 @@ typedef struct StrokeCache { float old_grab_location[3]; int symmetry; /* Symmetry index between 0 and 7 */ float view_normal[3], view_normal_symmetry[3]; - int last_dot[2]; /* Last location of stroke application */ int last_rake[2]; /* Last location of updating rake rotation */ } StrokeCache; @@ -849,15 +848,6 @@ static void do_symmetrical_brush_actions(Sculpt *sd, StrokeCache *cache) const char symm = sd->flags & 7; int i; - /* Brush spacing: only apply dot if next dot is far enough away */ - if((sd->brush->flag & BRUSH_SPACE) && !(sd->brush->flag & BRUSH_ANCHORED) && !cache->first_time) { - int dx = cache->last_dot[0] - cache->mouse[0]; - int dy = cache->last_dot[1] - cache->mouse[1]; - if(sqrt(dx*dx+dy*dy) < sd->brush->spacing) - return; - } - memcpy(cache->last_dot, cache->mouse, sizeof(int) * 2); - VecCopyf(cache->location, cache->true_location); VecCopyf(cache->grab_delta_symmetry, cache->grab_delta); cache->symmetry = 0; @@ -1050,16 +1040,21 @@ static void draw_paint_cursor(bContext *C, int x, int y, void *customdata) { Sculpt *sd= CTX_data_tool_settings(C)->sculpt; - glTranslatef((float)x, (float)y, 0.0f); - glColor4ub(255, 100, 100, 128); glEnable( GL_LINE_SMOOTH ); glEnable(GL_BLEND); + + glTranslatef((float)x, (float)y, 0.0f); glutil_draw_lined_arc(0.0, M_PI*2.0, sd->brush->size, 40); + glTranslatef((float)-x, (float)-y, 0.0f); + + if(sd->session && sd->session->cache && sd->brush && (sd->brush->flag & BRUSH_SMOOTH_STROKE)) { + ARegion *ar = CTX_wm_region(C); + sdrawline(x, y, sd->session->cache->mouse[0] - ar->winrct.xmin, sd->session->cache->mouse[1] - ar->winrct.ymin); + } + glDisable(GL_BLEND); glDisable( GL_LINE_SMOOTH ); - - glTranslatef((float)-x, (float)-y, 0.0f); } static void toggle_paint_cursor(bContext *C) @@ -1202,6 +1197,9 @@ static void sculpt_update_cache_invariants(Sculpt *sd, bContext *C, wmOperator * RNA_int_get_array(op->ptr, "initial_mouse", cache->initial_mouse); cache->depth = RNA_float_get(op->ptr, "depth"); + cache->mouse[0] = cache->initial_mouse[0]; + cache->mouse[1] = cache->initial_mouse[1]; + /* Truly temporary data that isn't stored in properties */ view3d_set_viewcontext(C, &cache->vc); @@ -1407,13 +1405,99 @@ static void sculpt_flush_update(bContext *C) ED_region_tag_redraw(ar); } +/* Returns zero if no sculpt changes should be made, non-zero otherwise */ +static int sculpt_smooth_stroke(Sculpt *s, int output[2], wmEvent *event) +{ + output[0] = event->x; + output[1] = event->y; + + if(s->brush->flag & BRUSH_SMOOTH_STROKE && s->brush->sculpt_tool != SCULPT_TOOL_GRAB) { + StrokeCache *cache = s->session->cache; + float u = .9, v = 1.0 - u; + int dx = cache->mouse[0] - event->x, dy = cache->mouse[1] - event->y; + int radius = 50; + + /* If the mouse is moving within the radius of the last move, + don't update the mouse position. This allows sharp turns. */ + if(dx*dx + dy*dy < radius*radius) + return 0; + + output[0] = event->x * v + cache->mouse[0] * u; + output[1] = event->y * v + cache->mouse[1] * u; + } + + return 1; +} + +/* Returns zero if the stroke dots should not be spaced, non-zero otherwise */ +int sculpt_space_stroke_enabled(Sculpt *s) +{ + Brush *br = s->brush; + return (br->flag & BRUSH_SPACE) && !(br->flag & BRUSH_ANCHORED) && (br->sculpt_tool != SCULPT_TOOL_GRAB); +} + +/* Put the location of the next sculpt stroke dot into the stroke RNA and apply it to the mesh */ +static void sculpt_brush_stroke_add_step(bContext *C, wmOperator *op, wmEvent *event, int mouse[2]) +{ + Sculpt *sd = CTX_data_tool_settings(C)->sculpt; + StrokeCache *cache = sd->session->cache; + PointerRNA itemptr; + float cur_depth; + float center[3]; + + cur_depth = read_cached_depth(&cache->vc, mouse[0], mouse[1]); + unproject(sd->session->cache->mats, center, mouse[0], mouse[1], cur_depth); + + /* Add to stroke */ + RNA_collection_add(op->ptr, "stroke", &itemptr); + RNA_float_set_array(&itemptr, "location", center); + RNA_int_set_array(&itemptr, "mouse", mouse); + RNA_boolean_set(&itemptr, "flip", event->shift); + sculpt_update_cache_variants(sd, &itemptr); + + sculpt_restore_mesh(sd); + do_symmetrical_brush_actions(sd, cache); + + sculpt_post_stroke_free(sd->session); +} + +/* For brushes with stroke spacing enabled, moves mouse in steps + towards the final mouse location. */ +static int sculpt_space_stroke(bContext *C, wmOperator *op, wmEvent *event, Sculpt *s, const int final_mouse[2]) +{ + StrokeCache *cache = s->session->cache; + int cnt = 0; + + if(sculpt_space_stroke_enabled(s)) { + float vec[2] = {final_mouse[0] - cache->mouse[0], final_mouse[1] - cache->mouse[1]}; + int mouse[2] = {cache->mouse[0], cache->mouse[1]}; + float length, scale; + int steps = 0, i; + + /* Normalize the vector between the last stroke dot and the goal */ + length = sqrt(vec[0]*vec[0] + vec[1]*vec[1]); + + if(length > FLT_EPSILON) { + scale = s->brush->spacing / length; + vec[0] *= scale; + vec[1] *= scale; + + steps = (int)(length / s->brush->spacing); + for(i = 0; i < steps; ++i, ++cnt) { + mouse[0] += vec[0]; + mouse[1] += vec[1]; + sculpt_brush_stroke_add_step(C, op, event, mouse); + } + } + } + + return cnt; +} + static int sculpt_brush_stroke_modal(bContext *C, wmOperator *op, wmEvent *event) { - PointerRNA itemptr; Sculpt *sd = CTX_data_tool_settings(C)->sculpt; ARegion *ar = CTX_wm_region(C); - float center[3]; - int mouse[2] = {event->x, event->y}; float cur_depth; sculpt_update_mesh_elements(C); @@ -1433,21 +1517,19 @@ static int sculpt_brush_stroke_modal(bContext *C, wmOperator *op, wmEvent *event } if(sd->session->cache) { - cur_depth = read_cached_depth(&sd->session->cache->vc, event->x, event->y); - unproject(sd->session->cache->mats, center, event->x, event->y, cur_depth); + int mouse[2]; - /* Add to stroke */ - RNA_collection_add(op->ptr, "stroke", &itemptr); - RNA_float_set_array(&itemptr, "location", center); - RNA_int_set_array(&itemptr, "mouse", mouse); - RNA_boolean_set(&itemptr, "flip", event->shift); - sculpt_update_cache_variants(sd, &itemptr); - - sculpt_restore_mesh(sd); - do_symmetrical_brush_actions(CTX_data_tool_settings(C)->sculpt, sd->session->cache); - - sculpt_flush_update(C); - sculpt_post_stroke_free(sd->session); + if(sculpt_smooth_stroke(sd, mouse, event)) { + if(sculpt_space_stroke_enabled(sd)) { + if(!sculpt_space_stroke(C, op, event, sd, mouse)) + ED_region_tag_redraw(ar); + } + else + sculpt_brush_stroke_add_step(C, op, event, mouse); + sculpt_flush_update(C); + } + else + ED_region_tag_redraw(ar); } /* Finished */ diff --git a/source/blender/editors/space_buttons/buttons_intern.h b/source/blender/editors/space_buttons/buttons_intern.h index 13ea778fb00..65c2976d57c 100644 --- a/source/blender/editors/space_buttons/buttons_intern.h +++ b/source/blender/editors/space_buttons/buttons_intern.h @@ -71,8 +71,8 @@ void MATERIAL_OT_new(struct wmOperatorType *ot); void TEXTURE_OT_new(struct wmOperatorType *ot); void WORLD_OT_new(struct wmOperatorType *ot); -void OBJECT_OT_particle_system_slot_add(struct wmOperatorType *ot); -void OBJECT_OT_particle_system_slot_remove(struct wmOperatorType *ot); +void OBJECT_OT_particle_system_add(struct wmOperatorType *ot); +void OBJECT_OT_particle_system_remove(struct wmOperatorType *ot); void PARTICLE_OT_new(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_buttons/buttons_ops.c b/source/blender/editors/space_buttons/buttons_ops.c index 6ca92674c6e..df3e8c62d37 100644 --- a/source/blender/editors/space_buttons/buttons_ops.c +++ b/source/blender/editors/space_buttons/buttons_ops.c @@ -412,7 +412,7 @@ void WORLD_OT_new(wmOperatorType *ot) /********************** particle system slot operators *********************/ -static int particle_system_slot_add_exec(bContext *C, wmOperator *op) +static int particle_system_add_exec(bContext *C, wmOperator *op) { Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; Scene *scene = CTX_data_scene(C); @@ -420,26 +420,26 @@ static int particle_system_slot_add_exec(bContext *C, wmOperator *op) if(!scene || !ob) return OPERATOR_CANCELLED; - object_add_particle_system_slot(scene, ob); + object_add_particle_system(scene, ob); WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); return OPERATOR_FINISHED; } -void OBJECT_OT_particle_system_slot_add(wmOperatorType *ot) +void OBJECT_OT_particle_system_add(wmOperatorType *ot) { /* identifiers */ ot->name= "Add Particle System Slot"; - ot->idname= "OBJECT_OT_particle_system_slot_add"; + ot->idname= "OBJECT_OT_particle_system_add"; /* api callbacks */ - ot->exec= particle_system_slot_add_exec; + ot->exec= particle_system_add_exec; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } -static int particle_system_slot_remove_exec(bContext *C, wmOperator *op) +static int particle_system_remove_exec(bContext *C, wmOperator *op) { Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; Scene *scene = CTX_data_scene(C); @@ -447,20 +447,20 @@ static int particle_system_slot_remove_exec(bContext *C, wmOperator *op) if(!scene || !ob) return OPERATOR_CANCELLED; - object_remove_particle_system_slot(scene, ob); + object_remove_particle_system(scene, ob); WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); return OPERATOR_FINISHED; } -void OBJECT_OT_particle_system_slot_remove(wmOperatorType *ot) +void OBJECT_OT_particle_system_remove(wmOperatorType *ot) { /* identifiers */ ot->name= "Remove Particle System Slot"; - ot->idname= "OBJECT_OT_particle_system_slot_remove"; + ot->idname= "OBJECT_OT_particle_system_remove"; /* api callbacks */ - ot->exec= particle_system_slot_remove_exec; + ot->exec= particle_system_remove_exec; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c index 7954d5254cc..b89a13ce218 100644 --- a/source/blender/editors/space_buttons/space_buttons.c +++ b/source/blender/editors/space_buttons/space_buttons.c @@ -220,8 +220,8 @@ void buttons_operatortypes(void) WM_operatortype_append(TEXTURE_OT_new); WM_operatortype_append(WORLD_OT_new); - WM_operatortype_append(OBJECT_OT_particle_system_slot_add); - WM_operatortype_append(OBJECT_OT_particle_system_slot_remove); + WM_operatortype_append(OBJECT_OT_particle_system_add); + WM_operatortype_append(OBJECT_OT_particle_system_remove); WM_operatortype_append(PARTICLE_OT_new); } @@ -331,6 +331,7 @@ static void buttons_area_listener(ScrArea *sa, wmNotifier *wmn) case NC_SCENE: switch(wmn->data) { case ND_FRAME: + case ND_MODE: ED_area_tag_redraw(sa); break; diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c index bb47d3458fe..02ee8f508c1 100644 --- a/source/blender/editors/space_file/file_draw.c +++ b/source/blender/editors/space_file/file_draw.c @@ -550,132 +550,4 @@ void file_draw_list(const bContext *C, ARegion *ar) } } -static void file_draw_fsmenu_category_name(ARegion *ar, const char *category_name, short *starty) -{ - short sx, sy; - int bmwidth = ar->v2d.cur.xmax - ar->v2d.cur.xmin - 2*TILE_BORDER_X - ICON_DEFAULT_WIDTH - 4; - int fontsize = file_font_pointsize(); - - sx = ar->v2d.cur.xmin + TILE_BORDER_X; - sy = *starty; - - UI_ThemeColor(TH_TEXT_HI); - file_draw_string(sx, sy, category_name, bmwidth, fontsize, FILE_SHORTEN_END); - - sy -= fontsize*2.0f; - - *starty= sy; -} - -static void file_draw_fsmenu_category(const bContext *C, ARegion *ar, FSMenuCategory category, short *starty) -{ - struct FSMenu* fsmenu = fsmenu_get(); - char bookmark[FILE_MAX]; - int nentries = fsmenu_get_nentries(fsmenu, category); - - short sx, sy, xpos, ypos; - int bmwidth = ar->v2d.cur.xmax - ar->v2d.cur.xmin - 2*TILE_BORDER_X - ICON_DEFAULT_WIDTH - 4; - int fontsize = file_font_pointsize(); - int cat_icon; - int i; - - sx = ar->v2d.cur.xmin + TILE_BORDER_X; - sy = *starty; - - switch(category) { - case FS_CATEGORY_SYSTEM: - cat_icon = ICON_DISK_DRIVE; break; - case FS_CATEGORY_BOOKMARKS: - cat_icon = ICON_BOOKMARKS; break; - case FS_CATEGORY_RECENT: - cat_icon = ICON_FILE_FOLDER; break; - } - - for (i=0; i< nentries && (sy > ar->v2d.cur.ymin) ;++i) { - char *fname = fsmenu_get_entry(fsmenu, category, i); - - if (fname) { - int sl; - BLI_strncpy(bookmark, fname, FILE_MAX); - - sl = strlen(bookmark)-1; - if (sl > 1) { - while (bookmark[sl] == '\\' || bookmark[sl] == '/') { - bookmark[sl] = '\0'; - sl--; - } - } - - if (fsmenu_is_selected(fsmenu, category, i) ) { - UI_ThemeColor(TH_HILITE); - uiRoundBox(sx, sy - fontsize*2.0f, ar->v2d.cur.xmax - TILE_BORDER_X, sy, 4.0f); - UI_ThemeColor(TH_TEXT); - } else { - UI_ThemeColor(TH_TEXT_HI); - } - - xpos = sx; - ypos = sy - (TILE_BORDER_Y * 0.5); - - file_draw_icon(xpos, ypos, cat_icon, ICON_DEFAULT_WIDTH, ICON_DEFAULT_WIDTH); - xpos += ICON_DEFAULT_WIDTH + 4; - file_draw_string(xpos, ypos, bookmark, bmwidth, fontsize, FILE_SHORTEN_FRONT); - sy -= fontsize*2.0; - fsmenu_set_pos(fsmenu, category, i, xpos, ypos); - } - } - - *starty = sy; -} - -void file_draw_fsmenu_operator(const bContext *C, ARegion *ar, wmOperator *op, short *starty) -{ - uiStyle *style= U.uistyles.first; - uiBlock *block; - uiLayout *layout; - int sy; - - sy= *starty; - - block= uiBeginBlock(C, ar, "file_options", UI_EMBOSS); - layout= uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, TILE_BORDER_X, sy, ar->winx-2*TILE_BORDER_X, 20, style); - - RNA_STRUCT_BEGIN(op->ptr, prop) { - if(strcmp(RNA_property_identifier(prop), "rna_type") == 0) - continue; - if(strcmp(RNA_property_identifier(prop), "filename") == 0) - continue; - - uiItemFullR(layout, NULL, 0, op->ptr, prop, -1, 0, 0, 0, 0); - } - RNA_STRUCT_END; - - uiBlockLayoutResolve(C, block, NULL, &sy); - uiEndBlock(C, block); - uiDrawBlock(C, block); - - *starty= sy; -} - -void file_draw_fsmenu(const bContext *C, ARegion *ar) -{ - SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C); - int linestep = file_font_pointsize()*2.0f; - short sy= ar->v2d.cur.ymax-2*TILE_BORDER_Y; - - file_draw_fsmenu_category_name(ar, "SYSTEM", &sy); - file_draw_fsmenu_category(C, ar, FS_CATEGORY_SYSTEM, &sy); - sy -= linestep; - file_draw_fsmenu_category_name(ar, "BOOKMARKS", &sy); - file_draw_fsmenu_category(C, ar, FS_CATEGORY_BOOKMARKS, &sy); - sy -= linestep; - file_draw_fsmenu_category_name(ar, "RECENT", &sy); - file_draw_fsmenu_category(C, ar, FS_CATEGORY_RECENT, &sy); - - if(sfile->op) { - sy -= linestep; - file_draw_fsmenu_category_name(ar, "OPTIONS", &sy); - file_draw_fsmenu_operator(C, ar, sfile->op, &sy); - } -} diff --git a/source/blender/editors/space_file/file_intern.h b/source/blender/editors/space_file/file_intern.h index 642189ad3fd..668e14c95e6 100644 --- a/source/blender/editors/space_file/file_intern.h +++ b/source/blender/editors/space_file/file_intern.h @@ -30,6 +30,9 @@ /* internal exports only */ +struct ARegion; +struct ARegionType; +struct SpaceFile; /* file_header.c */ void file_header_buttons(const bContext *C, ARegion *ar); @@ -45,7 +48,6 @@ void file_draw_buttons(const bContext *C, ARegion *ar); void file_calc_previews(const bContext *C, ARegion *ar); void file_draw_previews(const bContext *C, ARegion *ar); void file_draw_list(const bContext *C, ARegion *ar); -void file_draw_fsmenu(const bContext *C, ARegion *ar); /* file_ops.h */ struct wmOperatorType; @@ -56,6 +58,9 @@ void FILE_OT_select(struct wmOperatorType *ot); void FILE_OT_select_all_toggle(struct wmOperatorType *ot); void FILE_OT_select_border(struct wmOperatorType *ot); void FILE_OT_select_bookmark(struct wmOperatorType *ot); +void FILE_OT_add_bookmark(struct wmOperatorType *ot); +void FILE_OT_delete_bookmark(struct wmOperatorType *ot); +void FILE_OT_hidedot(struct wmOperatorType *ot); void FILE_OT_loadimages(struct wmOperatorType *ot); void FILE_OT_exec(struct wmOperatorType *ot); void FILE_OT_cancel(struct wmOperatorType *ot); @@ -66,11 +71,14 @@ void FILE_OT_bookmark_toggle(struct wmOperatorType *ot); int file_exec(bContext *C, struct wmOperator *unused); int file_cancel_exec(bContext *C, struct wmOperator *unused); int file_parent_exec(bContext *C, struct wmOperator *unused); -int file_hilight_set(SpaceFile *sfile, ARegion *ar, int mx, int my); +int file_hilight_set(struct SpaceFile *sfile, struct ARegion *ar, int mx, int my); /* filesel.c */ float file_string_width(const char* str); float file_font_pointsize(); +/* file_panels.c */ +void file_panels_register(struct ARegionType *art); + #endif /* ED_FILE_INTERN_H */ diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c index ab02147d020..aaa1793efbb 100644 --- a/source/blender/editors/space_file/file_ops.c +++ b/source/blender/editors/space_file/file_ops.c @@ -42,6 +42,8 @@ #include "ED_screen.h" #include "ED_fileselect.h" +#include "MEM_guardedalloc.h" + #include "RNA_access.h" #include "RNA_define.h" @@ -135,22 +137,15 @@ static void file_select(SpaceFile* sfile, ARegion* ar, const rcti* rect, short v params->active_file = last_file; if(file && S_ISDIR(file->type)) { - /* the path is too long and we are not going up! */ - if (strcmp(file->relname, ".") && - strcmp(file->relname, "..") && - strlen(params->dir) + strlen(file->relname) >= FILE_MAX ) + /* the path is too long! */ + if (strlen(params->dir) + strlen(file->relname) >= FILE_MAX ) { // XXX error("Path too long, cannot enter this directory"); } else { - if (strcmp(file->relname, "..")==0) { - /* avoids /../../ */ - BLI_parent_dir(params->dir); - } else { - strcat(params->dir, file->relname); - strcat(params->dir,"/"); - params->file[0] = '\0'; - BLI_cleanup_dir(G.sce, params->dir); - } + strcat(params->dir, file->relname); + strcat(params->dir,"/"); + params->file[0] = '\0'; + BLI_cleanup_dir(G.sce, params->dir); filelist_setdir(sfile->files, params->dir); filelist_free(sfile->files); params->active_file = -1; @@ -234,7 +229,7 @@ static int file_select_invoke(bContext *C, wmOperator *op, wmEvent *event) /* single select, deselect all selected first */ file_deselect_all(sfile); file_select(sfile, ar, &rect, val ); - WM_event_add_notifier(C, NC_WINDOW, NULL); + WM_event_add_notifier(C, NC_FILE|ND_PARAMS, NULL); } return OPERATOR_FINISHED; } @@ -299,75 +294,25 @@ void FILE_OT_select_all_toggle(wmOperatorType *ot) /* ---------- BOOKMARKS ----------- */ -static int file_select_bookmark_category(SpaceFile* sfile, ARegion* ar, short x, short y, FSMenuCategory category) -{ - struct FSMenu* fsmenu = fsmenu_get(); - int nentries = fsmenu_get_nentries(fsmenu, category); - int linestep = file_font_pointsize()*2.0f; - short xs, ys; - int i; - int selected = -1; - - for (i=0; i < nentries; ++i) { - fsmenu_get_pos(fsmenu, category, i, &xs, &ys); - if ( (y<=ys) && (y>ys-linestep) ) { - fsmenu_select_entry(fsmenu, category, i); - selected = i; - break; - } - } - return selected; -} - -static void file_select_bookmark(SpaceFile* sfile, ARegion* ar, short x, short y) -{ - float fx, fy; - int selected; - FSMenuCategory category = FS_CATEGORY_SYSTEM; - - if (BLI_in_rcti(&ar->v2d.mask, x, y)) { - char *entry; - - UI_view2d_region_to_view(&ar->v2d, x, y, &fx, &fy); - selected = file_select_bookmark_category(sfile, ar, fx, fy, FS_CATEGORY_SYSTEM); - if (selected<0) { - category = FS_CATEGORY_BOOKMARKS; - selected = file_select_bookmark_category(sfile, ar, fx, fy, category); - } - if (selected<0) { - category = FS_CATEGORY_RECENT; - selected = file_select_bookmark_category(sfile, ar, fx, fy, category); - } - - if (selected>=0) { - entry= fsmenu_get_entry(fsmenu_get(), category, selected); - /* which string */ - if (entry) { - FileSelectParams* params = sfile->params; - BLI_strncpy(params->dir, entry, sizeof(params->dir)); - BLI_cleanup_dir(G.sce, params->dir); - filelist_free(sfile->files); - filelist_setdir(sfile->files, params->dir); - params->file[0] = '\0'; - params->active_file = -1; - } - } - } -} - static int bookmark_select_invoke(bContext *C, wmOperator *op, wmEvent *event) { - ScrArea *sa= CTX_wm_area(C); - ARegion *ar= CTX_wm_region(C); SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C); - short x, y; + if(RNA_struct_find_property(op->ptr, "dir")) { + char entry[256]; + FileSelectParams* params = sfile->params; - x = event->x - ar->winrct.xmin; - y = event->y - ar->winrct.ymin; + RNA_string_get(op->ptr, "dir", entry); + BLI_strncpy(params->dir, entry, sizeof(params->dir)); + BLI_cleanup_dir(G.sce, params->dir); + filelist_free(sfile->files); + filelist_setdir(sfile->files, params->dir); + params->file[0] = '\0'; + params->active_file = -1; - file_select_bookmark(sfile, ar, x, y); - ED_area_tag_redraw(sa); + WM_event_add_notifier(C, NC_FILE|ND_PARAMS, NULL); + } + return OPERATOR_FINISHED; } @@ -380,8 +325,75 @@ void FILE_OT_select_bookmark(wmOperatorType *ot) /* api callbacks */ ot->invoke= bookmark_select_invoke; ot->poll= ED_operator_file_active; + + RNA_def_string(ot->srna, "dir", "", 256, "Dir", ""); } +static int bookmark_add_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + ScrArea *sa= CTX_wm_area(C); + SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C); + struct FSMenu* fsmenu = fsmenu_get(); + struct FileSelectParams* params= ED_fileselect_get_params(sfile); + + if (params->dir[0] != '\0') { + char name[FILE_MAX]; + + fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, params->dir, 0, 1); + BLI_make_file_string("/", name, BLI_gethome(), ".Bfs"); + fsmenu_write_file(fsmenu, name); + } + + ED_area_tag_redraw(sa); + return OPERATOR_FINISHED; +} + +void FILE_OT_add_bookmark(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Add Bookmark"; + ot->idname= "FILE_OT_add_bookmark"; + + /* api callbacks */ + ot->invoke= bookmark_add_invoke; + ot->poll= ED_operator_file_active; +} + +static int bookmark_delete_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + ScrArea *sa= CTX_wm_area(C); + SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C); + struct FSMenu* fsmenu = fsmenu_get(); + int nentries = fsmenu_get_nentries(fsmenu, FS_CATEGORY_BOOKMARKS); + if(RNA_struct_find_property(op->ptr, "index")) { + int index = RNA_int_get(op->ptr, "index"); + if ( (index >-1) && (index < nentries)) { + char name[FILE_MAX]; + + fsmenu_remove_entry(fsmenu, FS_CATEGORY_BOOKMARKS, index); + BLI_make_file_string("/", name, BLI_gethome(), ".Bfs"); + fsmenu_write_file(fsmenu, name); + ED_area_tag_redraw(sa); + } + } + + return OPERATOR_FINISHED; +} + +void FILE_OT_delete_bookmark(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Delete Bookmark"; + ot->idname= "FILE_OT_delete_bookmark"; + + /* api callbacks */ + ot->invoke= bookmark_delete_invoke; + ot->poll= ED_operator_file_active; + + RNA_def_int(ot->srna, "index", -1, -1, 20000, "Index", "", -1, 20000); +} + + static int loadimages_invoke(bContext *C, wmOperator *op, wmEvent *event) { ScrArea *sa= CTX_wm_area(C); @@ -548,7 +560,7 @@ int file_parent_exec(bContext *C, wmOperator *unused) filelist_free(sfile->files); sfile->params->active_file = -1; } - ED_area_tag_redraw(CTX_wm_area(C)); + WM_event_add_notifier(C, NC_FILE|ND_FILELIST, NULL); return OPERATOR_FINISHED; @@ -575,8 +587,8 @@ int file_refresh_exec(bContext *C, wmOperator *unused) filelist_setdir(sfile->files, sfile->params->dir); filelist_free(sfile->files); sfile->params->active_file = -1; - } - ED_area_tag_redraw(CTX_wm_area(C)); + } + WM_event_add_notifier(C, NC_FILE|ND_FILELIST, NULL); return OPERATOR_FINISHED; @@ -594,14 +606,58 @@ void FILE_OT_refresh(struct wmOperatorType *ot) ot->poll= ED_operator_file_active; /* <- important, handler is on window level */ } +int file_hidedot_exec(bContext *C, wmOperator *unused) +{ + SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C); + + if(sfile->params) { + sfile->params->flag ^= FILE_HIDE_DOT; + filelist_free(sfile->files); + sfile->params->active_file = -1; + WM_event_add_notifier(C, NC_FILE|ND_FILELIST, NULL); + } + + return OPERATOR_FINISHED; + +} + + +void FILE_OT_hidedot(struct wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Toggle Hide Dot Files"; + ot->idname= "FILE_OT_hidedot"; + + /* api callbacks */ + ot->exec= file_hidedot_exec; + ot->poll= ED_operator_file_active; /* <- important, handler is on window level */ +} + struct ARegion *file_buttons_region(struct ScrArea *sa) { - ARegion *ar; + ARegion *ar, *arnew; for(ar= sa->regionbase.first; ar; ar= ar->next) if(ar->regiontype==RGN_TYPE_CHANNELS) return ar; - return NULL; + + /* add subdiv level; after header */ + for(ar= sa->regionbase.first; ar; ar= ar->next) + if(ar->regiontype==RGN_TYPE_HEADER) + break; + + /* is error! */ + if(ar==NULL) return NULL; + + arnew= MEM_callocN(sizeof(ARegion), "buttons for file panels"); + + BLI_insertlinkafter(&sa->regionbase, ar, arnew); + arnew->regiontype= RGN_TYPE_CHANNELS; + arnew->alignment= RGN_ALIGN_LEFT; + + arnew->flag = RGN_FLAG_HIDDEN; + + return arnew; } int file_bookmark_toggle_exec(bContext *C, wmOperator *unused) diff --git a/source/blender/editors/space_file/file_panels.c b/source/blender/editors/space_file/file_panels.c new file mode 100644 index 00000000000..29c759d43c0 --- /dev/null +++ b/source/blender/editors/space_file/file_panels.c @@ -0,0 +1,165 @@ +/** + * $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, Andrea Weikert + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "BKE_context.h" +#include "BKE_screen.h" + +#include "BLI_blenlib.h" + +#include "DNA_screen_types.h" +#include "DNA_space_types.h" +#include "DNA_userdef_types.h" +#include "DNA_windowmanager_types.h" + +#include "MEM_guardedalloc.h" + +#include "RNA_access.h" + +#include "UI_interface.h" +#include "UI_resources.h" +#include "UI_view2d.h" + +#include "file_intern.h" +#include "fsmenu.h" + +#include + +static void do_file_panel_events(bContext *C, void *arg, int event) +{ + +} + +static void file_panel_category(const bContext *C, Panel *pa, FSMenuCategory category, int icon, int allow_delete) +{ + uiBlock *block; + uiStyle *style= U.uistyles.first; + int i; + int fontsize = file_font_pointsize(); + struct FSMenu* fsmenu = fsmenu_get(); + int nentries = fsmenu_get_nentries(fsmenu, category); + + uiLayoutSetAlignment(pa->layout, UI_LAYOUT_ALIGN_LEFT); + block= uiLayoutFreeBlock(pa->layout); + uiBlockSetHandleFunc(block, do_file_panel_events, NULL); + uiBlockSetEmboss(block, UI_EMBOSSP); + uiBlockBeginAlign(block); + for (i=0; i< nentries;++i) { + char dir[FILE_MAX]; + char temp[FILE_MAX]; + uiLayout* layout = uiLayoutRow(pa->layout, UI_LAYOUT_ALIGN_LEFT); + char *entry = fsmenu_get_entry(fsmenu, category, i); + + /* create nice bookmark name, shows last directory in the full path currently */ + BLI_strncpy(temp, entry, FILE_MAX); + BLI_add_slash(temp); + BLI_getlastdir(temp, dir, FILE_MAX); + BLI_del_slash(dir); + + /* operator shows the short bookmark name, should eventually have tooltip */ + uiItemStringO(layout, dir, icon, "FILE_OT_select_bookmark", "dir", entry); + if (allow_delete && fsmenu_can_save(fsmenu, category, i) ) + uiItemIntO(layout, "", ICON_X, "FILE_OT_delete_bookmark", "index", i); + } + uiBlockEndAlign(block); +} + +static void file_panel_system(const bContext *C, Panel *pa) +{ + file_panel_category(C, pa, FS_CATEGORY_SYSTEM, ICON_DISK_DRIVE, 0); +} + +static void file_panel_bookmarks(const bContext *C, Panel *pa) +{ + file_panel_category(C, pa, FS_CATEGORY_BOOKMARKS, ICON_BOOKMARKS, 1); +} + + +static void file_panel_recent(const bContext *C, Panel *pa) +{ + file_panel_category(C, pa, FS_CATEGORY_RECENT, ICON_FILE_FOLDER, 0); +} + + +static void file_panel_operator(const bContext *C, Panel *pa) +{ + SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C); + struct wmOperator *op = sfile ? sfile->op : NULL; + uiBlock *block; + int sy; + + block= uiLayoutFreeBlock(pa->layout); + uiBlockSetHandleFunc(block, do_file_panel_events, NULL); + + sy= 0; + if (op) { + uiBlockBeginAlign(block); + RNA_STRUCT_BEGIN(op->ptr, prop) { + if(strcmp(RNA_property_identifier(prop), "rna_type") == 0) + continue; + if(strcmp(RNA_property_identifier(prop), "filename") == 0) + continue; + + uiItemFullR(pa->layout, NULL, 0, op->ptr, prop, -1, 0, 0, 0, 0); + } + RNA_STRUCT_END; + uiBlockEndAlign(block); + } + uiBlockLayoutResolve(C, block, NULL, &sy); + uiEndBlock(C, block); + uiDrawBlock(C, block); +} + + +void file_panels_register(ARegionType *art) +{ + PanelType *pt; + + pt= MEM_callocN(sizeof(PanelType), "spacetype file system directories"); + strcpy(pt->idname, "FILE_PT_system"); + strcpy(pt->label, "System"); + pt->draw= file_panel_system; + BLI_addtail(&art->paneltypes, pt); + + pt= MEM_callocN(sizeof(PanelType), "spacetype file bookmarks"); + strcpy(pt->idname, "FILE_PT_bookmarks"); + strcpy(pt->label, "Bookmarks"); + pt->draw= file_panel_bookmarks; + BLI_addtail(&art->paneltypes, pt); + + pt= MEM_callocN(sizeof(PanelType), "spacetype file recent directories"); + strcpy(pt->idname, "FILE_PT_recent"); + strcpy(pt->label, "Recent"); + pt->draw= file_panel_recent; + BLI_addtail(&art->paneltypes, pt); + + pt= MEM_callocN(sizeof(PanelType), "spacetype file operator properties"); + strcpy(pt->idname, "FILE_PT_operator"); + strcpy(pt->label, "Operator"); + pt->draw= file_panel_operator; + BLI_addtail(&art->paneltypes, pt); +} \ No newline at end of file diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index 766dec7c064..573aed72728 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -823,16 +823,16 @@ void filelist_sort(struct FileList* filelist, short sort) int num;/* , act= 0; */ switch(sort) { - case FILE_SORTALPHA: + case FILE_SORT_ALPHA: qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_name); break; - case FILE_SORTDATE: + case FILE_SORT_TIME: qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_date); break; - case FILE_SORTSIZE: + case FILE_SORT_SIZE: qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_size); break; - case FILE_SORTEXTENS: + case FILE_SORT_EXTENSION: qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_extension); } diff --git a/source/blender/editors/space_file/filelist.h b/source/blender/editors/space_file/filelist.h index f10c89926d6..e929e028849 100644 --- a/source/blender/editors/space_file/filelist.h +++ b/source/blender/editors/space_file/filelist.h @@ -49,7 +49,6 @@ void filelist_free_icons(); struct FileList * filelist_copy(struct FileList* filelist); int filelist_find(struct FileList* filelist, char *file); void filelist_free(struct FileList* filelist); -void filelist_freelib(struct FileList* filelist); void filelist_sort(struct FileList* filelist, short sort); int filelist_numfiles(struct FileList* filelist); const char * filelist_dir(struct FileList* filelist); diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c index 9c0bcc6b991..e1d81138e5a 100644 --- a/source/blender/editors/space_file/filesel.c +++ b/source/blender/editors/space_file/filesel.c @@ -84,7 +84,7 @@ FileSelectParams* ED_fileselect_get_params(struct SpaceFile *sfile) { if (!sfile->params) { - ED_fileselect_set_params(sfile, "", "/", 0, FILE_SHORTDISPLAY, 0, FILE_SORTALPHA); + ED_fileselect_set_params(sfile, "", "/", 0, FILE_SHORTDISPLAY, 0, FILE_SORT_ALPHA); } return sfile->params; } diff --git a/source/blender/editors/space_file/fsmenu.c b/source/blender/editors/space_file/fsmenu.c index 59e8dcf82e6..a87ad4c4fd8 100644 --- a/source/blender/editors/space_file/fsmenu.c +++ b/source/blender/editors/space_file/fsmenu.c @@ -65,7 +65,6 @@ struct _FSMenuEntry { char *path; short save; - short xs, ys; }; typedef struct FSMenu @@ -74,9 +73,6 @@ typedef struct FSMenu FSMenuEntry *fsmenu_bookmarks; FSMenuEntry *fsmenu_recent; - FSMenuCategory selected_category; - int selected_entry; - } FSMenu; static FSMenu *g_fsmenu = NULL; @@ -89,17 +85,6 @@ struct FSMenu* fsmenu_get(void) return g_fsmenu; } -void fsmenu_select_entry(struct FSMenu* fsmenu, FSMenuCategory category, int index) -{ - fsmenu->selected_category = category; - fsmenu->selected_entry = index; -} - -int fsmenu_is_selected(struct FSMenu* fsmenu, FSMenuCategory category, int index) -{ - return (category==fsmenu->selected_category) && (index==fsmenu->selected_entry); -} - static FSMenuEntry *fsmenu_get_category(struct FSMenu* fsmenu, FSMenuCategory category) { FSMenuEntry *fsms = NULL; @@ -154,36 +139,16 @@ char *fsmenu_get_entry(struct FSMenu* fsmenu, FSMenuCategory category, int idx) return fsme?fsme->path:NULL; } -void fsmenu_set_pos(struct FSMenu* fsmenu, FSMenuCategory category, int idx, short xs, short ys) +short fsmenu_can_save (struct FSMenu* fsmenu, FSMenuCategory category, int idx) { FSMenuEntry *fsme; for (fsme= fsmenu_get_category(fsmenu, category); fsme && idx; fsme= fsme->next) idx--; - if (fsme) { - fsme->xs = xs; - fsme->ys = ys; - } + return fsme?fsme->save:0; } -int fsmenu_get_pos (struct FSMenu* fsmenu, FSMenuCategory category, int idx, short* xs, short* ys) -{ - FSMenuEntry *fsme; - - for (fsme= fsmenu_get_category(fsmenu, category); fsme && idx; fsme= fsme->next) - idx--; - - if (fsme) { - *xs = fsme->xs; - *ys = fsme->ys; - return 1; - } - - return 0; -} - - void fsmenu_insert_entry(struct FSMenu* fsmenu, FSMenuCategory category, char *path, int sorted, short save) { FSMenuEntry *prev; diff --git a/source/blender/editors/space_file/fsmenu.h b/source/blender/editors/space_file/fsmenu.h index c51c45b7dc4..2cab622d523 100644 --- a/source/blender/editors/space_file/fsmenu.h +++ b/source/blender/editors/space_file/fsmenu.h @@ -52,22 +52,15 @@ int fsmenu_get_nentries (struct FSMenu* fsmenu, FSMenuCategory category); */ char* fsmenu_get_entry (struct FSMenu* fsmenu, FSMenuCategory category, int index); -void fsmenu_select_entry (struct FSMenu* fsmenu, FSMenuCategory category, int index); - -int fsmenu_is_selected (struct FSMenu* fsmenu, FSMenuCategory category, int index); - - /** Sets the position of the fsmenu entry at @a index */ -void fsmenu_set_pos (struct FSMenu* fsmenu, FSMenuCategory category, int index, short xs, short ys); - - /** Returns the position of the fsmenu entry at @a index. return value is 1 if successful, 0 otherwise */ -int fsmenu_get_pos (struct FSMenu* fsmenu, FSMenuCategory category, int index, short* xs, short* ys); - /** Inserts a new fsmenu entry with the given @a path. * Duplicate entries are not added. * @param sorted Should entry be inserted in sorted order? */ void fsmenu_insert_entry (struct FSMenu* fsmenu, FSMenuCategory category, char *path, int sorted, short save); + /** Return whether the entry was created by the user and can be saved and deleted */ +short fsmenu_can_save (struct FSMenu* fsmenu, FSMenuCategory category, int index); + /** Removes the fsmenu entry at the given @a index. */ void fsmenu_remove_entry (struct FSMenu* fsmenu, FSMenuCategory category, int index); diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index 37d8f2bffa4..156c7d6f9be 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -163,6 +163,46 @@ static SpaceLink *file_duplicate(SpaceLink *sl) return (SpaceLink *)sfilen; } +static void file_refresh(const bContext *C, ScrArea *sa) +{ + SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C); + FileSelectParams *params = ED_fileselect_get_params(sfile); + + if (!sfile->files) { + sfile->files = filelist_new(); + filelist_setdir(sfile->files, params->dir); + params->active_file = -1; // added this so it opens nicer (ton) + } + filelist_hidedot(sfile->files, params->flag & FILE_HIDE_DOT); + if (filelist_empty(sfile->files)) + { + filelist_readdir(sfile->files); + } + filelist_setfilter(sfile->files, params->flag & FILE_FILTER ? params->filter : 0); + if(params->sort!=FILE_SORT_NONE) filelist_sort(sfile->files, params->sort); +} + +static void file_listener(ScrArea *sa, wmNotifier *wmn) +{ + SpaceFile* sfile = (SpaceFile*)sa->spacedata.first; + + /* context changes */ + switch(wmn->category) { + case NC_FILE: + switch (wmn->data) { + case ND_FILELIST: + if (sfile->files) filelist_free(sfile->files); + ED_area_tag_refresh(sa); + ED_area_tag_redraw(sa); + break; + case ND_PARAMS: + ED_area_tag_refresh(sa); + ED_area_tag_redraw(sa); + break; + } + break; + } +} /* add handlers, stuff you only do once or on area/region changes */ static void file_main_area_init(wmWindowManager *wm, ARegion *ar) @@ -188,31 +228,9 @@ static void file_main_area_draw(const bContext *C, ARegion *ar) View2D *v2d= &ar->v2d; View2DScrollers *scrollers; float col[3]; - - if (!sfile->files) { - sfile->files = filelist_new(); - filelist_setdir(sfile->files, params->dir); - params->active_file = -1; // added this so it opens nicer (ton) - } layout = ED_fileselect_get_layout(sfile, ar); - if (filelist_empty(sfile->files)) - { - unsigned int filter = 0; - filelist_hidedot(sfile->files, params->flag & FILE_HIDE_DOT); - if (params->flag & FILE_FILTER) { - filter = params->filter ; - } else { - filter = 0; - } - - filelist_setfilter(sfile->files, filter); - filelist_readdir(sfile->files); - - if(params->sort!=FILE_SORTALPHA) filelist_sort(sfile->files, params->sort); - } - /* clear and setup matrix */ UI_GetThemeColor3fv(TH_BACK, col); glClearColor(col[0], col[1], col[2], 0.0); @@ -274,20 +292,25 @@ void file_operatortypes(void) WM_operatortype_append(FILE_OT_parent); WM_operatortype_append(FILE_OT_refresh); WM_operatortype_append(FILE_OT_bookmark_toggle); + WM_operatortype_append(FILE_OT_add_bookmark); + WM_operatortype_append(FILE_OT_delete_bookmark); + WM_operatortype_append(FILE_OT_hidedot); } /* NOTE: do not add .blend file reading on this level */ void file_keymap(struct wmWindowManager *wm) { ListBase *keymap= WM_keymap_listbase(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_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); WM_keymap_add_item(keymap, "FILE_OT_highlight", MOUSEMOVE, KM_ANY, 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); + WM_keymap_add_item(keymap, "FILE_OT_hidedot", HKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "FILE_OT_loadimages", TIMER1, KM_ANY, KM_ANY, 0); - + keymap= WM_keymap_listbase(wm, "FileBookmark", SPACE_FILE, 0); WM_keymap_add_item(keymap, "FILE_OT_select_bookmark", LEFTMOUSE, KM_PRESS, 0, 0); } @@ -295,56 +318,31 @@ void file_keymap(struct wmWindowManager *wm) static void file_channel_area_init(wmWindowManager *wm, ARegion *ar) { - ListBase *keymap; - - UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy); - - /* own keymap */ - keymap= WM_keymap_listbase(wm, "FileBookmark", SPACE_FILE, 0); - WM_event_add_keymap_handler_bb(&ar->handlers, keymap, NULL, NULL); + ED_region_panels_init(wm, ar); } static void file_channel_area_draw(const bContext *C, ARegion *ar) { - View2D *v2d= &ar->v2d; - float col[3]; + ED_region_panels(C, ar, 1, NULL); +} - UI_GetThemeColor3fv(TH_PANEL, col); - glClearColor(col[0], col[1], col[2], 0.0); - glClear(GL_COLOR_BUFFER_BIT); - - /* data... */ - UI_view2d_view_ortho(C, v2d); - - file_draw_fsmenu(C, ar); +static void file_channel_area_listener(ARegion *ar, wmNotifier *wmn) +{ + /* context changes */ + switch(wmn->category) { + + } } /* add handlers, stuff you only do once or on area/region changes */ static void file_header_area_init(wmWindowManager *wm, ARegion *ar) { - UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy); + ED_region_header_init(ar); } static void file_header_area_draw(const bContext *C, ARegion *ar) { - float col[3]; - - /* clear */ - if(ED_screen_area_active(C)) - UI_GetThemeColor3fv(TH_HEADER, col); - else - UI_GetThemeColor3fv(TH_HEADERDESEL, col); - - glClearColor(col[0], col[1], col[2], 0.0); - glClear(GL_COLOR_BUFFER_BIT); - - /* set view2d view matrix for scrolling (without scrollers) */ - UI_view2d_view_ortho(C, &ar->v2d); - - file_header_buttons(C, ar); - - /* restore view matrix? */ - UI_view2d_view_restore(C); + ED_region_header(C, ar); } /* add handlers, stuff you only do once or on area/region changes */ @@ -386,6 +384,8 @@ void ED_spacetype_file(void) st->free= file_free; st->init= file_init; st->duplicate= file_duplicate; + st->refresh= file_refresh; + st->listener= file_listener; st->operatortypes= file_operatortypes; st->keymap= file_keymap; @@ -405,6 +405,7 @@ void ED_spacetype_file(void) art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D; art->init= file_header_area_init; art->draw= file_header_area_draw; + // art->listener= file_header_area_listener; BLI_addhead(&st->regiontypes, art); /* regions: ui */ @@ -421,10 +422,13 @@ void ED_spacetype_file(void) art->regionid = RGN_TYPE_CHANNELS; art->minsizex= 240; art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D; + art->listener= file_channel_area_listener; art->init= file_channel_area_init; art->draw= file_channel_area_draw; BLI_addhead(&st->regiontypes, art); - + file_panels_register(art); + + BKE_spacetype_register(st); } diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index a08a23c1263..edf9bcbd896 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -1088,7 +1088,7 @@ static void image_pack_cb(bContext *C, void *ima_v, void *iuser_v) } if ((G.fileflags & G_AUTOPACK) == 0) { - unpackImage(ima, PF_ASK); + unpackImage(NULL, ima, PF_ASK); /* XXX report errors */ ED_undo_push(C, "Unpack image"); } } @@ -1097,7 +1097,7 @@ static void image_pack_cb(bContext *C, void *ima_v, void *iuser_v) if (ibuf && (ibuf->userflags & IB_BITMAPDIRTY)) { // XXX error("Can't pack painted image. Save image or use Repack as PNG."); } else { - ima->packedfile = newPackedFile(ima->name); + ima->packedfile = newPackedFile(NULL, ima->name); /* XXX report errors */ ED_undo_push(C, "Pack image"); } } diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 8f9bb0d05fe..24781cc115e 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1114,7 +1114,7 @@ static int pack_exec(bContext *C, wmOperator *op) if(as_png) BKE_image_memorypack(ima); else - ima->packedfile= newPackedFile(ima->name); + ima->packedfile= newPackedFile(op->reports, ima->name); return OPERATOR_FINISHED; } @@ -1162,13 +1162,76 @@ void IMAGE_OT_pack(wmOperatorType *ot) /********************* unpack operator *********************/ +/* XXX move this to some place where it can be reused */ + +const EnumPropertyItem unpack_method_items[] = { + {PF_USE_LOCAL, "USE_LOCAL", 0, "Use Local File", ""}, + {PF_WRITE_LOCAL, "WRITE_LOCAL", 0, "Write Local File (overwrite existing)", ""}, + {PF_USE_ORIGINAL, "USE_ORIGINAL", 0, "Use Original File", ""}, + {PF_WRITE_ORIGINAL, "WRITE_ORIGINAL", 0, "Write Original File (overwrite existing)", ""}, + {0, NULL, 0, NULL, NULL}}; + +void unpack_menu(bContext *C, char *opname, char *abs_name, char *folder, PackedFile *pf) +{ + uiPopupMenu *pup; + uiLayout *layout; + char line[FILE_MAXDIR + FILE_MAXFILE + 100]; + char local_name[FILE_MAXDIR + FILE_MAX], fi[FILE_MAX]; + + strcpy(local_name, abs_name); + BLI_splitdirstring(local_name, fi); + sprintf(local_name, "//%s/%s", folder, fi); + + pup= uiPupMenuBegin(C, "Unpack file", 0); + layout= uiPupMenuLayout(pup); + + uiItemEnumO(layout, "Remove Pack", 0, opname, "method", PF_REMOVE); + + if(strcmp(abs_name, local_name)) { + switch(checkPackedFile(local_name, pf)) { + case PF_NOFILE: + sprintf(line, "Create %s", local_name); + uiItemEnumO(layout, line, 0, opname, "method", PF_WRITE_LOCAL); + break; + case PF_EQUAL: + sprintf(line, "Use %s (identical)", local_name); + uiItemEnumO(layout, line, 0, opname, "method", PF_USE_LOCAL); + break; + case PF_DIFFERS: + sprintf(line, "Use %s (differs)", local_name); + uiItemEnumO(layout, line, 0, opname, "method", PF_USE_LOCAL); + sprintf(line, "Overwrite %s", local_name); + uiItemEnumO(layout, line, 0, opname, "method", PF_WRITE_LOCAL); + break; + } + } + + switch(checkPackedFile(abs_name, pf)) { + case PF_NOFILE: + sprintf(line, "Create %s", abs_name); + uiItemEnumO(layout, line, 0, opname, "method", PF_WRITE_ORIGINAL); + break; + case PF_EQUAL: + sprintf(line, "Use %s (identical)", abs_name); + uiItemEnumO(layout, line, 0, opname, "method", PF_USE_ORIGINAL); + break; + case PF_DIFFERS: + sprintf(line, "Use %s (differs)", local_name); + uiItemEnumO(layout, line, 0, opname, "method", PF_USE_ORIGINAL); + sprintf(line, "Overwrite %s", local_name); + uiItemEnumO(layout, line, 0, opname, "method", PF_WRITE_ORIGINAL); + break; + } + + uiPupMenuEnd(C, pup); +} + static int unpack_exec(bContext *C, wmOperator *op) { Image *ima= CTX_data_edit_image(C); + int method= RNA_enum_get(op->ptr, "method"); - if(!ima) - return OPERATOR_CANCELLED; - if(!ima->packedfile) + if(!ima || !ima->packedfile) return OPERATOR_CANCELLED; if(ima->source==IMA_SRC_SEQUENCE || ima->source==IMA_SRC_MOVIE) { @@ -1179,7 +1242,27 @@ static int unpack_exec(bContext *C, wmOperator *op) if(G.fileflags & G_AUTOPACK) BKE_report(op->reports, RPT_WARNING, "AutoPack is enabled, so image will be packed again on file save."); - unpackImage(ima, PF_ASK); + unpackImage(op->reports, ima, method); + + return OPERATOR_FINISHED; +} + +static int unpack_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + Image *ima= CTX_data_edit_image(C); + + if(!ima || !ima->packedfile) + return OPERATOR_CANCELLED; + + if(ima->source==IMA_SRC_SEQUENCE || ima->source==IMA_SRC_MOVIE) { + BKE_report(op->reports, RPT_ERROR, "Can't unpack movie or image sequence."); + return OPERATOR_CANCELLED; + } + + if(G.fileflags & G_AUTOPACK) + BKE_report(op->reports, RPT_WARNING, "AutoPack is enabled, so image will be packed again on file save."); + + unpack_menu(C, "IMAGE_OT_unpack", ima->name, "textures", ima->packedfile); return OPERATOR_FINISHED; } @@ -1192,10 +1275,14 @@ void IMAGE_OT_unpack(wmOperatorType *ot) /* api callbacks */ ot->exec= unpack_exec; + ot->invoke= unpack_invoke; ot->poll= space_image_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* properties */ + RNA_def_enum(ot->srna, "method", unpack_method_items, PF_USE_LOCAL, "Method", "How to unpack."); } /******************** sample image operator ********************/ diff --git a/source/blender/editors/space_info/info_header.c b/source/blender/editors/space_info/info_header.c deleted file mode 100644 index 7b65a70117c..00000000000 --- a/source/blender/editors/space_info/info_header.c +++ /dev/null @@ -1,507 +0,0 @@ -/** - * $Id$ - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2008 Blender Foundation. - * All rights reserved. - * - * - * Contributor(s): Blender Foundation - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#include -#include - -#include "DNA_packedFile_types.h" -#include "DNA_space_types.h" -#include "DNA_scene_types.h" -#include "DNA_screen_types.h" -#include "DNA_userdef_types.h" -#include "DNA_windowmanager_types.h" - -#include "MEM_guardedalloc.h" - -#include "BLI_blenlib.h" -#include "BLI_bpath.h" - -#include "BKE_context.h" -#include "BKE_global.h" -#include "BKE_image.h" -#include "BKE_main.h" -#include "BKE_packedFile.h" -#include "BKE_screen.h" - -#include "ED_screen.h" -#include "ED_types.h" -#include "ED_util.h" - -#include "WM_api.h" -#include "WM_types.h" - -#include "BIF_gl.h" -#include "BIF_glutil.h" - -#include "UI_interface.h" -#include "UI_resources.h" -#include "UI_view2d.h" - -#include "IMB_imbuf_types.h" - -#include "info_intern.h" - -static int pupmenu() {return 0;} -static int okee() {return 0;} -static int error() {return 0;} - -/* ************************ header area region *********************** */ - -#define B_STOPRENDER 1 -#define B_STOPCAST 2 -#define B_STOPANIM 3 - -static void do_viewmenu(bContext *C, void *arg, int event) -{ -} - -static uiBlock *dummy_viewmenu(bContext *C, ARegion *ar, void *arg_unused) -{ - ScrArea *curarea= CTX_wm_area(C); - uiBlock *block; - short yco= 0, menuwidth=120; - - block= uiBeginBlock(C, ar, "dummy_viewmenu", UI_EMBOSSP); - uiBlockSetButmFunc(block, do_viewmenu, NULL); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Nothing yet", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 1, 3, ""); - - if(curarea->headertype==HEADERTOP) { - uiBlockSetDirection(block, UI_DOWN); - } - else { - uiBlockSetDirection(block, UI_TOP); - uiBlockFlipOrder(block); - } - - uiTextBoundsBlock(block, 50); - uiEndBlock(C, block); - - return block; -} - -static int buttons_do_unpack() -{ - int how; - char menu[2048]; - char *line = menu; - int ret_value = 1, count = 0; - - count = countPackedFiles(); - - if(!count) { - pupmenu("No packed files. Autopack disabled"); - return ret_value; - } - if (count == 1) - line += sprintf(line, "Unpack 1 file%%t"); - else - line += sprintf(line, "Unpack %d files%%t", count); - - line += sprintf(line, "|Use files in current directory (create when necessary)%%x%d", PF_USE_LOCAL); - line += sprintf(line, "|Write files to current directory (overwrite existing files)%%x%d", PF_WRITE_LOCAL); - line += sprintf(line, "|%%l|Use files in original location (create when necessary)%%x%d", PF_USE_ORIGINAL); - line += sprintf(line, "|Write files to original location (overwrite existing files)%%x%d", PF_WRITE_ORIGINAL); - line += sprintf(line, "|%%l|Disable AutoPack, keep all packed files %%x%d", PF_KEEP); - line += sprintf(line, "|Ask for each file %%x%d", PF_ASK); - - how = pupmenu(menu); - - if(how == -1) - ret_value = 0; - else { - if (how != PF_KEEP) unpackAll(how); - G.fileflags &= ~G_AUTOPACK; - } - - return ret_value; -} - -static void check_packAll() -{ - // first check for dirty images - Image *ima; - - for(ima = G.main->image.first; ima; ima= ima->id.next) { - if (ima->ibufs.first) { /* XXX FIX */ - ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); - - if (ibuf && (ibuf->userflags &= IB_BITMAPDIRTY)) - break; - } - } - - if (ima == NULL || okee("Some images are painted on. These changes will be lost. Continue ?")) { - packAll(); - G.fileflags |= G_AUTOPACK; - } -} - -static void do_info_externalfiles(bContext *C, void *arg, int event) -{ - switch (event) { - - case 1: /* pack data */ - check_packAll(); - break; - case 3: /* unpack data */ - if (buttons_do_unpack() != 0) { - /* Clear autopack bit only if user selected one of the unpack options */ - G.fileflags &= ~G_AUTOPACK; - } - break; - case 10: /* make all paths relative */ - if (G.relbase_valid) { - int tot,changed,failed,linked; - char str[512]; - char txtname[24]; /* text block name */ - txtname[0] = '\0'; - makeFilesRelative(txtname, &tot, &changed, &failed, &linked); - if (failed) sprintf(str, "Make Relative%%t|Total files %i|Changed %i|Failed %i, See Text \"%s\"|Linked %i", tot, changed, failed, txtname, linked); - else sprintf(str, "Make Relative%%t|Total files %i|Changed %i|Failed %i|Linked %i", tot, changed, failed, linked); - pupmenu(str); - } else { - pupmenu("Can't set relative paths with an unsaved blend file"); - } - break; - case 11: /* make all paths absolute */ - { - int tot,changed,failed,linked; - char str[512]; - char txtname[24]; /* text block name */ - txtname[0] = '\0'; - makeFilesAbsolute(txtname, &tot, &changed, &failed, &linked); - sprintf(str, "Make Absolute%%t|Total files %i|Changed %i|Failed %i|Linked %i", tot, changed, failed, linked); - if (failed) sprintf(str, "Make Absolute%%t|Total files %i|Changed %i|Failed %i, See Text \"%s\"|Linked %i", tot, changed, failed, txtname, linked); - else sprintf(str, "Make Absolute%%t|Total files %i|Changed %i|Failed %i|Linked %i", tot, changed, failed, linked); - - pupmenu(str); - } - break; - case 12: /* check images exist */ - { - char txtname[24]; /* text block name */ - txtname[0] = '\0'; - - /* run the missing file check */ - checkMissingFiles( txtname ); - - if (txtname[0] == '\0') { - okee("No external files missing"); - } else { - char str[128]; - sprintf(str, "Missing files listed in Text \"%s\"", txtname ); - error(str); - } - } - break; - case 13: /* search for referenced files that are not available */ -// XXX if(curarea->spacetype==SPACE_INFO) { -// ScrArea *sa; -// sa= closest_bigger_area(); -// areawinset(sa->win); -// } -// activate_fileselect(FILE_SPECIAL, "Find Missing Files", "", findMissingFiles); - break; - } - -} - - -uiBlock *info_externalfiles(bContext *C, ARegion *ar, void *arg_unused) -{ - uiBlock *block; - short yco = 20, menuwidth = 120; - - block= uiBeginBlock(C, ar, "info_externalfiles", UI_EMBOSSP); - uiBlockSetButmFunc(block, do_info_externalfiles, NULL); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Pack into .blend file", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 1, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Unpack into Files...", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 3, ""); - - uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Make all Paths Relative", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 10, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Make all Paths Absolute", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 11, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Report Missing Files...", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 12, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Find Missing Files...", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 13, ""); - - uiBlockSetDirection(block, UI_RIGHT); - uiTextBoundsBlock(block, 60); - return block; -} - - - -static void info_filemenu(bContext *C, uiLayout *layout, void *arg_unused) -{ - - uiLayoutSetOperatorContext(layout, WM_OP_EXEC_AREA); - uiItemO(layout, NULL, 0, "WM_OT_read_homefile"); - uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_AREA); - uiItemO(layout, NULL, 0, "WM_OT_open_mainfile"); -// uiDefIconTextBlockBut(block, info_openrecentmenu, NULL, ICON_RIGHTARROW_THIN, "Open Recent",0, yco-=20, 120, 19, ""); -// uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Recover Last Session", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 15, ""); - - uiItemS(layout); - - uiLayoutSetOperatorContext(layout, WM_OP_EXEC_AREA); - uiItemO(layout, NULL, 0, "WM_OT_save_mainfile"); - uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_AREA); - uiItemO(layout, NULL, 0, "WM_OT_save_as_mainfile"); - -#if 0 - if(U.flag & USER_FILECOMPRESS) { - uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Compress File", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 35, "Enable file compression"); - } else { - uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Compress File", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 35, "Enable file compression"); - } - - uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Save Rendered Image...|F3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Screenshot Subwindow|Ctrl F3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 24, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Screenshot All|Ctrl Shift F3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 25, ""); -#if GAMEBLENDER == 1 - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Save Game As Runtime...", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 22, ""); -#endif - uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Save Default Settings|Ctrl U", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 31, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Load Factory Settings", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 32, ""); - - - uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Append or Link|Shift F1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Append or Link (Image Browser)|Ctrl F1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, ""); -// uiDefIconTextBlockBut(block, info_file_importmenu, NULL, ICON_RIGHTARROW_THIN, "Import", 0, yco-=20, menuwidth, 19, ""); -// uiDefIconTextBlockBut(block, info_file_exportmenu, NULL, ICON_RIGHTARROW_THIN, "Export", 0, yco-=20, menuwidth, 19, ""); - - uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - - uiDefIconTextBlockBut(block, info_externalfiles, NULL, ICON_RIGHTARROW_THIN, "External Data",0, yco-=20, 120, 19, ""); - - uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Quit Blender|Ctrl Q", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 13, ""); - uiBlockSetDirection(block, UI_DOWN); - uiTextBoundsBlock(block, 80); - - uiEndBlock(C, block); - return block; -#endif -} - - -static void do_info_buttons(bContext *C, void *arg, int event) -{ - switch(event) { - case B_STOPRENDER: - G.afbreek= 1; - break; - case B_STOPCAST: - WM_jobs_stop(CTX_wm_manager(C), CTX_wm_screen(C)); - break; - case B_STOPANIM: - ED_screen_animation_timer(C, 0, 0); - break; - } -} - -static void screen_idpoin_handle(bContext *C, ID *id, int event) -{ - switch(event) { - case UI_ID_BROWSE: - /* exception: can't set screens inside of area/region handers */ - WM_event_add_notifier(C, NC_SCREEN|ND_SCREENBROWSE, id); - break; - case UI_ID_DELETE: - ED_undo_push(C, ""); - break; - case UI_ID_RENAME: - break; - case UI_ID_ADD_NEW: - /* XXX not implemented */ - break; - case UI_ID_OPEN: - /* XXX not implemented */ - break; - case UI_ID_ALONE: - /* XXX not implemented */ - break; - case UI_ID_PIN: - break; - } -} - -static void scene_idpoin_handle(bContext *C, ID *id, int event) -{ - switch(event) { - case UI_ID_BROWSE: - /* exception: can't set screens inside of area/region handers */ - WM_event_add_notifier(C, NC_SCENE|ND_SCENEBROWSE, id); - break; - case UI_ID_DELETE: - ED_undo_push(C, ""); - break; - case UI_ID_RENAME: - break; - case UI_ID_ADD_NEW: - /* XXX not implemented */ - break; - case UI_ID_OPEN: - /* XXX not implemented */ - break; - case UI_ID_ALONE: - /* XXX not implemented */ - break; - case UI_ID_PIN: - break; - } -} - -static void operator_call_cb(struct bContext *C, void *arg1, void *arg2) -{ - wmOperatorType *ot= arg2; - - if(ot) - 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) -{ - wmOperatorType *ot = WM_operatortype_first(); - - for(; ot; ot= ot->next) { - - if(BLI_strcasestr(ot->name, str)) { - if(ot->poll==NULL || ot->poll((bContext *)C)) { - char name[256]; - int len= strlen(ot->name); - - /* display name for menu, can hold hotkey */ - BLI_strncpy(name, ot->name, 256); - - /* check for hotkey */ - if(len < 256-6) { - if(WM_key_event_operator_string(C, ot->idname, WM_OP_EXEC_DEFAULT, NULL, &name[len+1], 256-len-1)) - name[len]= '|'; - } - - if(0==uiSearchItemAdd(items, name, ot, 0)) - break; - } - } - } -} - -void info_header_buttons(const bContext *C, ARegion *ar) -{ - wmWindow *win= CTX_wm_window(C); - bScreen *screen= CTX_wm_screen(C); - ScrArea *sa= CTX_wm_area(C); - uiBlock *block; - int xco, yco= 3; - - block= uiBeginBlock(C, ar, "header buttons", UI_EMBOSS); - uiBlockSetHandleFunc(block, do_info_buttons, NULL); - - xco= ED_area_header_standardbuttons(C, block, yco); - - if((sa->flag & HEADER_NO_PULLDOWN)==0) { - int xmax; - - xmax= GetButStringLength("File"); - uiDefMenuBut(block, info_filemenu, NULL, "File", xco, yco, xmax-3, 20, ""); - xco+= xmax; - - xmax= GetButStringLength("Add"); - uiDefPulldownBut(block, dummy_viewmenu, sa, "Add", xco, yco, xmax-3, 20, ""); - xco+= xmax; - - xmax= GetButStringLength("Timeline"); - uiDefPulldownBut(block, dummy_viewmenu, sa, "Timeline", xco, yco, xmax-3, 20, ""); - xco+= xmax; - - xmax= GetButStringLength("Game"); - uiDefPulldownBut(block, dummy_viewmenu, sa, "Game", xco, yco, xmax-3, 20, ""); - xco+= xmax; - - xmax= GetButStringLength("Render"); - uiDefPulldownBut(block, dummy_viewmenu, sa, "Render", xco, yco, xmax-3, 20, ""); - xco+= xmax; - - xmax= GetButStringLength("Help"); - uiDefPulldownBut(block, dummy_viewmenu, NULL, "Help", xco, yco, xmax-3, 20, ""); - xco+= xmax; - } - - uiBlockSetEmboss(block, UI_EMBOSS); - - if(screen->full==0) { - xco= uiDefIDPoinButs(block, CTX_data_main(C), NULL, (ID*)win->screen, ID_SCR, NULL, xco, yco, - screen_idpoin_handle, UI_ID_BROWSE|UI_ID_RENAME|UI_ID_ADD_NEW|UI_ID_DELETE); - xco += 8; - xco= uiDefIDPoinButs(block, CTX_data_main(C), NULL, (ID*)screen->scene, ID_SCE, NULL, xco, yco, - scene_idpoin_handle, UI_ID_BROWSE|UI_ID_RENAME|UI_ID_ADD_NEW|UI_ID_DELETE); - xco += 8; - } - - if(WM_jobs_test(CTX_wm_manager(C), CTX_data_scene(C))) { - uiDefIconTextBut(block, BUT, B_STOPRENDER, ICON_REC, "Render", xco+5,yco,75,19, NULL, 0.0f, 0.0f, 0, 0, "Stop rendering"); - xco+= 80; - } - if(WM_jobs_test(CTX_wm_manager(C), CTX_wm_screen(C))) { - uiDefIconTextBut(block, BUT, B_STOPCAST, ICON_REC, "Capture", xco+5,yco,85,19, NULL, 0.0f, 0.0f, 0, 0, "Stop screencast"); - xco+= 90; - } - if(screen->animtimer) { - uiDefIconTextBut(block, BUT, B_STOPANIM, ICON_REC, "Anim Player", xco+5,yco,85,19, NULL, 0.0f, 0.0f, 0, 0, "Stop animation playback"); - xco+= 90; - } - - { - static char search[256]= ""; - uiBut *but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, xco+5, yco, 120, 19, ""); - - uiButSetSearchFunc(but, operator_search_cb, NULL, operator_call_cb); - - xco+= 125; - } - - - /* always as last */ - UI_view2d_totRect_set(&ar->v2d, xco+XIC+80, ar->v2d.tot.ymax-ar->v2d.tot.ymin); - - uiEndBlock(C, block); - uiDrawBlock(C, block); -} - - diff --git a/source/blender/editors/space_info/info_intern.h b/source/blender/editors/space_info/info_intern.h index 213c0688f20..519364b58d9 100644 --- a/source/blender/editors/space_info/info_intern.h +++ b/source/blender/editors/space_info/info_intern.h @@ -30,10 +30,17 @@ /* internal exports only */ +struct wmOperatorType; /* info_header.c */ void info_header_buttons(const bContext *C, ARegion *ar); +void FILE_OT_pack_all(struct wmOperatorType *ot); +void FILE_OT_unpack_all(struct wmOperatorType *ot); +void FILE_OT_make_paths_relative(struct wmOperatorType *ot); +void FILE_OT_make_paths_absolute(struct wmOperatorType *ot); +void FILE_OT_report_missing_files(struct wmOperatorType *ot); +void FILE_OT_find_missing_files(struct wmOperatorType *ot); #endif /* ED_INFO_INTERN_H */ diff --git a/source/blender/editors/space_info/info_ops.c b/source/blender/editors/space_info/info_ops.c new file mode 100644 index 00000000000..56f925a2e81 --- /dev/null +++ b/source/blender/editors/space_info/info_ops.c @@ -0,0 +1,397 @@ +/** + * $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) 2008 Blender Foundation. + * All rights reserved. + * + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include +#include + +#include "DNA_packedFile_types.h" +#include "DNA_space_types.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" +#include "DNA_userdef_types.h" +#include "DNA_windowmanager_types.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" +#include "BLI_bpath.h" + +#include "BKE_context.h" +#include "BKE_global.h" +#include "BKE_image.h" +#include "BKE_main.h" +#include "BKE_packedFile.h" +#include "BKE_report.h" +#include "BKE_screen.h" + +#include "ED_screen.h" +#include "ED_types.h" +#include "ED_util.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "BIF_gl.h" +#include "BIF_glutil.h" + +#include "UI_interface.h" +#include "UI_resources.h" + +#include "IMB_imbuf_types.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "WM_types.h" + +#include "info_intern.h" + +/********************* pack all operator *********************/ + +static int pack_all_exec(bContext *C, wmOperator *op) +{ + Main *bmain= CTX_data_main(C); + + packAll(bmain, op->reports); + G.fileflags |= G_AUTOPACK; + + return OPERATOR_FINISHED; +} + +static int pack_all_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + Main *bmain= CTX_data_main(C); + Image *ima; + ImBuf *ibuf; + + // first check for dirty images + for(ima=bmain->image.first; ima; ima=ima->id.next) { + if(ima->ibufs.first) { /* XXX FIX */ + ibuf= BKE_image_get_ibuf(ima, NULL); + + if(ibuf && (ibuf->userflags & IB_BITMAPDIRTY)) + break; + } + } + + if(ima) { + uiPupMenuOkee(C, "FILE_OT_pack_all", "Some images are painted on. These changes will be lost. Continue?"); + return OPERATOR_CANCELLED; + } + + return pack_all_exec(C, op); +} + +void FILE_OT_pack_all(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Pack All"; + ot->idname= "FILE_OT_pack_all"; + + /* api callbacks */ + ot->exec= pack_all_exec; + ot->invoke= pack_all_invoke; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +/********************* unpack all operator *********************/ + +static const EnumPropertyItem unpack_all_method_items[] = { + {PF_USE_LOCAL, "USE_LOCAL", 0, "Use files in current directory (create when necessary)", ""}, + {PF_WRITE_LOCAL, "WRITE_LOCAL", 0, "Write files to current directory (overwrite existing files)", ""}, + {PF_USE_ORIGINAL, "USE_ORIGINAL", 0, "Use files in original location (create when necessary)", ""}, + {PF_WRITE_ORIGINAL, "WRITE_ORIGINAL", 0, "Write files to original location (overwrite existing files)", ""}, + {PF_KEEP, "KEEP", 0, "Disable AutoPack, keep all packed files", ""}, + {PF_ASK, "ASK", 0, "Ask for each file", ""}, + {0, NULL, 0, NULL, NULL}}; + +static int unpack_all_exec(bContext *C, wmOperator *op) +{ + Main *bmain= CTX_data_main(C); + int method= RNA_enum_get(op->ptr, "method"); + + if(method != PF_KEEP) unpackAll(bmain, op->reports, method); /* XXX PF_ASK can't work here */ + G.fileflags &= ~G_AUTOPACK; + + return OPERATOR_FINISHED; +} + +static int unpack_all_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + Main *bmain= CTX_data_main(C); + uiPopupMenu *pup; + uiLayout *layout; + char title[128]; + int count = 0; + + count = countPackedFiles(bmain); + + if(!count) { + BKE_report(op->reports, RPT_WARNING, "No packed files. Autopack disabled."); + G.fileflags &= ~G_AUTOPACK; + return OPERATOR_CANCELLED; + } + + if(count == 1) + sprintf(title, "Unpack 1 file"); + else + sprintf(title, "Unpack %d files", count); + + pup= uiPupMenuBegin(C, title, 0); + layout= uiPupMenuLayout(pup); + + uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT); + uiItemsEnumO(layout, "FILE_OT_unpack_all", "method"); + + uiPupMenuEnd(C, pup); + + return OPERATOR_CANCELLED; +} + +void FILE_OT_unpack_all(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Unpack All"; + ot->idname= "FILE_OT_unpack_all"; + + /* api callbacks */ + ot->exec= unpack_all_exec; + ot->invoke= unpack_all_invoke; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* properties */ + RNA_def_enum(ot->srna, "method", unpack_all_method_items, PF_USE_LOCAL, "Method", "How to unpack."); +} + +/********************* make paths relative operator *********************/ + +static int make_paths_relative_exec(bContext *C, wmOperator *op) +{ + char txtname[24]; /* text block name */ + int tot, changed, failed, linked; + + if(!G.relbase_valid) { + BKE_report(op->reports, RPT_WARNING, "Can't set relative paths with an unsaved blend file."); + return OPERATOR_CANCELLED; + } + + txtname[0] = '\0'; + makeFilesRelative(txtname, &tot, &changed, &failed, &linked); + + if(failed) + BKE_reportf(op->reports, RPT_ERROR, "Total files %i|Changed %i|Failed %i, See Text \"%s\"|Linked %i", tot, changed, failed, txtname, linked); + else + BKE_reportf(op->reports, RPT_INFO, "Total files %i|Changed %i|Failed %i|Linked %i", tot, changed, failed, linked); + + return OPERATOR_FINISHED; +} + +void FILE_OT_make_paths_relative(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Make All Paths Relative"; + ot->idname= "FILE_OT_make_paths_relative"; + + /* api callbacks */ + ot->exec= make_paths_relative_exec; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +/********************* make paths absolute operator *********************/ + +static int make_paths_absolute_exec(bContext *C, wmOperator *op) +{ + char txtname[24]; /* text block name */ + int tot, changed, failed, linked; + + if(!G.relbase_valid) { + BKE_report(op->reports, RPT_WARNING, "Can't set absolute paths with an unsaved blend file."); + return OPERATOR_CANCELLED; + } + + txtname[0] = '\0'; + makeFilesAbsolute(txtname, &tot, &changed, &failed, &linked); + + if(failed) + BKE_reportf(op->reports, RPT_ERROR, "Total files %i|Changed %i|Failed %i, See Text \"%s\"|Linked %i", tot, changed, failed, txtname, linked); + else + BKE_reportf(op->reports, RPT_INFO, "Total files %i|Changed %i|Failed %i|Linked %i", tot, changed, failed, linked); + + return OPERATOR_FINISHED; +} + +void FILE_OT_make_paths_absolute(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Make All Paths Absolute"; + ot->idname= "FILE_OT_make_paths_absolute"; + + /* api callbacks */ + ot->exec= make_paths_absolute_exec; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +/********************* report missing files operator *********************/ + +static int report_missing_files_exec(bContext *C, wmOperator *op) +{ + char txtname[24]; /* text block name */ + + txtname[0] = '\0'; + + /* run the missing file check */ + checkMissingFiles(txtname); + + if(txtname[0] == '\0') + BKE_report(op->reports, RPT_INFO, "No external files missing."); + else + BKE_reportf(op->reports, RPT_ERROR, "Missing files listed in Text \"%s\"", txtname); + + return OPERATOR_FINISHED; +} + +void FILE_OT_report_missing_files(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Report Missing Files..."; + ot->idname= "FILE_OT_report_missing_files"; + + /* api callbacks */ + ot->exec= report_missing_files_exec; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +/********************* find missing files operator *********************/ + +static int find_missing_files_exec(bContext *C, wmOperator *op) +{ + char *filename; + + filename= RNA_string_get_alloc(op->ptr, "filename", NULL, 0); + findMissingFiles(filename); + MEM_freeN(filename); + + return OPERATOR_FINISHED; +} + +static int find_missing_files_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + /* XXX file open button text "Find Missing Files" */ + WM_event_add_fileselect(C, op); + return OPERATOR_RUNNING_MODAL; +} + +void FILE_OT_find_missing_files(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Find Missing Files..."; + ot->idname= "FILE_OT_find_missing_files"; + + /* api callbacks */ + ot->exec= find_missing_files_exec; + ot->invoke= find_missing_files_invoke; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* properties */ + RNA_def_string_file_path(ot->srna, "filename", "", FILE_MAX, "Filename", "File path of image to open."); +} + +#if 0 +static void info_filemenu(bContext *C, uiLayout *layout, void *arg_unused) +{ + + uiLayoutSetOperatorContext(layout, WM_OP_EXEC_AREA); + uiItemO(layout, NULL, 0, "WM_OT_read_homefile"); + uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_AREA); + uiItemO(layout, NULL, 0, "WM_OT_open_mainfile"); +// uiDefIconTextBlockBut(block, info_openrecentmenu, NULL, ICON_RIGHTARROW_THIN, "Open Recent",0, yco-=20, 120, 19, ""); +// uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Recover Last Session", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 15, ""); + + uiItemS(layout); + + uiLayoutSetOperatorContext(layout, WM_OP_EXEC_AREA); + uiItemO(layout, NULL, 0, "WM_OT_save_mainfile"); + uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_AREA); + uiItemO(layout, NULL, 0, "WM_OT_save_as_mainfile"); + +#if 0 + if(U.flag & USER_FILECOMPRESS) { + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Compress File", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 35, "Enable file compression"); + } else { + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Compress File", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 35, "Enable file compression"); + } + + uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); + + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Save Rendered Image...|F3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Screenshot Subwindow|Ctrl F3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 24, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Screenshot All|Ctrl Shift F3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 25, ""); +#if GAMEBLENDER == 1 + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Save Game As Runtime...", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 22, ""); +#endif + uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); + + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Save Default Settings|Ctrl U", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 31, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Load Factory Settings", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 32, ""); + + + uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); + + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Append or Link|Shift F1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Append or Link (Image Browser)|Ctrl F1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, ""); +// uiDefIconTextBlockBut(block, info_file_importmenu, NULL, ICON_RIGHTARROW_THIN, "Import", 0, yco-=20, menuwidth, 19, ""); +// uiDefIconTextBlockBut(block, info_file_exportmenu, NULL, ICON_RIGHTARROW_THIN, "Export", 0, yco-=20, menuwidth, 19, ""); + + uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); + + uiDefIconTextBlockBut(block, info_externalfiles, NULL, ICON_RIGHTARROW_THIN, "External Data",0, yco-=20, 120, 19, ""); + + uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); + + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Quit Blender|Ctrl Q", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 13, ""); + uiBlockSetDirection(block, UI_DOWN); + uiTextBoundsBlock(block, 80); + + uiEndBlock(C, block); + return block; +#endif +} +#endif + diff --git a/source/blender/editors/space_info/space_info.c b/source/blender/editors/space_info/space_info.c index d72ecd60da9..7b24e8f4e07 100644 --- a/source/blender/editors/space_info/space_info.c +++ b/source/blender/editors/space_info/space_info.c @@ -151,7 +151,12 @@ static void info_main_area_draw(const bContext *C, ARegion *ar) void info_operatortypes(void) { - + WM_operatortype_append(FILE_OT_pack_all); + WM_operatortype_append(FILE_OT_unpack_all); + WM_operatortype_append(FILE_OT_make_paths_relative); + WM_operatortype_append(FILE_OT_make_paths_absolute); + WM_operatortype_append(FILE_OT_report_missing_files); + WM_operatortype_append(FILE_OT_find_missing_files); } void info_keymap(struct wmWindowManager *wm) @@ -162,29 +167,12 @@ void info_keymap(struct wmWindowManager *wm) /* add handlers, stuff you only do once or on area/region changes */ static void info_header_area_init(wmWindowManager *wm, ARegion *ar) { - UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy); + ED_region_header_init(ar); } static void info_header_area_draw(const bContext *C, ARegion *ar) { - float col[3]; - - /* clear */ - if(ED_screen_area_active(C)) - UI_GetThemeColor3fv(TH_HEADER, col); - else - UI_GetThemeColor3fv(TH_HEADERDESEL, col); - - glClearColor(col[0], col[1], col[2], 0.0); - glClear(GL_COLOR_BUFFER_BIT); - - /* set view2d view matrix for scrolling (without scrollers) */ - UI_view2d_view_ortho(C, &ar->v2d); - - info_header_buttons(C, ar); - - /* restore view matrix? */ - UI_view2d_view_restore(C); + ED_region_header(C, ar); } static void info_main_area_listener(ARegion *ar, wmNotifier *wmn) diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c index 79ea90864f3..5edcd203e16 100644 --- a/source/blender/editors/space_view3d/view3d_header.c +++ b/source/blender/editors/space_view3d/view3d_header.c @@ -4557,6 +4557,7 @@ static void view3d_sculpt_menu(bContext *C, uiLayout *layout, void *arg_unused) uiItemR(layout, NULL, 0, &rna, "rake", 0, 0, 0); uiItemR(layout, NULL, 0, &rna, "anchored", 0, 0, 0); uiItemR(layout, NULL, 0, &rna, "space", 0, 0, 0); + uiItemR(layout, NULL, 0, &rna, "smooth_stroke", 0, 0, 0); uiItemR(layout, NULL, 0, &rna, "flip_direction", 0, 0, 0); } diff --git a/source/blender/editors/space_view3d/view3d_toolbar.c b/source/blender/editors/space_view3d/view3d_toolbar.c index 34a935103a7..ea365d59ac7 100644 --- a/source/blender/editors/space_view3d/view3d_toolbar.c +++ b/source/blender/editors/space_view3d/view3d_toolbar.c @@ -204,7 +204,7 @@ static uiBlock *tool_search_menu(bContext *C, ARegion *ar, void *arg_listbase) uiDefBut(block, LABEL, 0, "", 10, 15, 150, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL); but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, OP_MAX_TYPENAME, 10, 0, 150, 19, ""); - uiButSetSearchFunc(but, operator_search_cb, arg_listbase, operator_call_cb); + uiButSetSearchFunc(but, operator_search_cb, arg_listbase, operator_call_cb, NULL); uiBoundsBlock(block, 6); uiBlockSetDirection(block, UI_DOWN); diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index 782d426641f..b57f4a91004 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -1431,6 +1431,9 @@ static int game_engine_exec(bContext *C, wmOperator *unused) Scene *startscene = CTX_data_scene(C); #if GAMEBLENDER == 1 + + view3d_operator_needs_opengl(C); + SaveState(C); StartKetsjiShell(C, 1); RestoreState(C); diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h index 8ce0b439b29..93a974c1180 100644 --- a/source/blender/makesdna/DNA_brush_types.h +++ b/source/blender/makesdna/DNA_brush_types.h @@ -84,6 +84,7 @@ typedef struct Brush { #define BRUSH_ANCHORED 256 #define BRUSH_DIR_IN 512 #define BRUSH_SPACE 1024 +#define BRUSH_SMOOTH_STROKE 2048 /* Brush.blend */ #define BRUSH_BLEND_MIX 0 diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index d0cd169905f..3549cdbe75f 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -439,6 +439,9 @@ typedef struct ToolSettings { VPaint *wpaint; /* weight paint */ Sculpt *sculpt; + /* Vertex groups */ + float vgroup_weight; + /* Subdivide Settings */ short cornertype; short editbutflag; @@ -470,7 +473,6 @@ typedef struct ToolSettings { float uvcalc_radius; float uvcalc_cubesize; float uvcalc_margin; - float pad; short uvcalc_mapdir; short uvcalc_mapalign; short uvcalc_flag; @@ -537,7 +539,7 @@ typedef struct ToolSettings { /* Alt+RMB option */ char edge_mode; - /* transform */ + /* Transform */ short snap_mode, snap_flag, snap_target; short proportional, prop_mode; } ToolSettings; diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h index 4891f44e1cd..d9d68490425 100644 --- a/source/blender/makesdna/DNA_screen_types.h +++ b/source/blender/makesdna/DNA_screen_types.h @@ -53,6 +53,7 @@ typedef struct bScreen { ListBase regionbase; /* screen level regions (menus), runtime only */ struct Scene *scene; + struct Scene *newscene; /* temporary when switching */ short full; /* fade out? */ short winid; /* winid from WM, starts with 1 */ @@ -104,6 +105,9 @@ typedef struct Panel { /* the part from uiBlock that needs saved in file */ int sortorder; /* panels are aligned according to increasing sortorder */ struct Panel *paneltab; /* this panel is tabbed in *paneltab */ void *activedata; /* runtime for panel manipulation */ + + int list_scroll, list_size; + char list_search[64]; } Panel; typedef struct Header { diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index f66c0c31fda..329a3aac148 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -165,6 +165,48 @@ typedef struct SpaceSeq { struct bGPdata *gpd; /* grease-pencil data */ } SpaceSeq; +typedef struct FileSelectParams { + char title[24]; /* title, also used for the text of the execute button */ + char dir[240]; /* directory */ + char file[80]; /* file */ + + short flag; /* settings for filter, hiding files and display mode */ + short sort; /* sort order */ + short display; /* display mode flag */ + short filter; /* filter when (flags & FILE_FILTER) is true */ + + /* XXX - temporary, better move to filelist */ + short active_bookmark; + short pad; + int active_file; + int selstate; + + /* XXX --- still unused -- */ + short f_fp; /* show font preview */ + short menu; /* currently selected option in pupmenu */ + char fp_str[8]; /* string to use for font preview */ + + char *pupmenu; /* allows menu for save options - result stored in menup */ + + /* XXX --- end unused -- */ +} FileSelectParams; + +/* FileSelectParams.display */ +enum FileDisplayTypeE { + FILE_SHORTDISPLAY = 1, + FILE_LONGDISPLAY, + FILE_IMGDISPLAY +}; + +/* FileSelectParams.sort */ +enum FileSortTypeE { + FILE_SORT_NONE = 0, + FILE_SORT_ALPHA = 1, + FILE_SORT_EXTENSION, + FILE_SORT_TIME, + FILE_SORT_SIZE +}; + typedef struct SpaceFile { SpaceLink *next, *prev; ListBase regionbase; /* storage of regions for inactive spaces */ @@ -555,12 +597,6 @@ typedef struct SpaceImaSel { #define FILE_FILTER 256 #define FILE_BOOKMARKS 512 -/* sfile->sort */ -#define FILE_SORTALPHA 0 -#define FILE_SORTDATE 1 -#define FILE_SORTSIZE 2 -#define FILE_SORTEXTENS 3 - /* files in filesel list: 2=ACTIVE */ #define HILITE 1 #define BLENDERFILE 4 diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h index e02d2984771..b63fb35c193 100644 --- a/source/blender/makesdna/DNA_windowmanager_types.h +++ b/source/blender/makesdna/DNA_windowmanager_types.h @@ -88,7 +88,8 @@ typedef struct wmWindow { int winid, pad; /* winid also in screens, is for retrieving this window after read */ - struct bScreen *screen; /* active screen */ + struct bScreen *screen; /* active screen */ + struct bScreen *newscreen; /* temporary when switching */ char screenname[32]; /* MAX_ID_NAME for matching window with active screen after file read */ short posx, posy, sizex, sizey; /* window coords */ diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index cf74a863401..c0a1c979147 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -174,6 +174,7 @@ extern StructRNA RNA_ExplodeModifier; extern StructRNA RNA_ExpressionController; extern StructRNA RNA_Event; extern StructRNA RNA_FCurve; +extern StructRNA RNA_FileSelectParams; extern StructRNA RNA_FModifier; extern StructRNA RNA_FModifierCycles; extern StructRNA RNA_FModifierEnvelope; @@ -374,6 +375,7 @@ extern StructRNA RNA_SpaceNLA; extern StructRNA RNA_SpaceOutliner; extern StructRNA RNA_SpaceSequenceEditor; extern StructRNA RNA_SpaceTextEditor; +extern StructRNA RNA_SpaceFileBrowser; extern StructRNA RNA_SpaceUVEditor; extern StructRNA RNA_SpeedControlSequence; extern StructRNA RNA_SpotLamp; @@ -605,6 +607,14 @@ int RNA_property_collection_length(PointerRNA *ptr, PropertyRNA *prop); int RNA_property_collection_lookup_int(PointerRNA *ptr, PropertyRNA *prop, int key, PointerRNA *r_ptr); int RNA_property_collection_lookup_string(PointerRNA *ptr, PropertyRNA *prop, const char *key, PointerRNA *r_ptr); +/* efficient functions to set properties for arrays */ +int RNA_property_collection_raw_array(PointerRNA *ptr, PropertyRNA *prop, PropertyRNA *itemprop, RawArray *array); +int RNA_property_collection_raw_get(struct ReportList *reports, PointerRNA *ptr, PropertyRNA *prop, char *propname, void *array, RawPropertyType type, int len); +int RNA_property_collection_raw_set(struct ReportList *reports, PointerRNA *ptr, PropertyRNA *prop, char *propname, void *array, RawPropertyType type, int len); +int RNA_raw_type_sizeof(RawPropertyType type); +RawPropertyType RNA_property_raw_type(PropertyRNA *prop); + + /* to create ID property groups */ void RNA_property_pointer_add(PointerRNA *ptr, PropertyRNA *prop); void RNA_property_pointer_remove(PointerRNA *ptr, PropertyRNA *prop); diff --git a/source/blender/makesrna/RNA_types.h b/source/blender/makesrna/RNA_types.h index 75f52ededd0..923191cba78 100644 --- a/source/blender/makesrna/RNA_types.h +++ b/source/blender/makesrna/RNA_types.h @@ -110,7 +110,9 @@ typedef enum PropertyFlag { PROP_BUILTIN = 128, PROP_EXPORT = 256, PROP_RUNTIME = 512, - PROP_IDPROPERTY = 1024 + PROP_IDPROPERTY = 1024, + PROP_RAW_ACCESS = 8192, + PROP_RAW_ARRAY = 16384, } PropertyFlag; typedef struct CollectionPropertyIterator { @@ -132,6 +134,21 @@ typedef struct CollectionPointerLink { PointerRNA ptr; } CollectionPointerLink; +typedef enum RawPropertyType { + PROP_RAW_CHAR, + PROP_RAW_SHORT, + PROP_RAW_INT, + PROP_RAW_FLOAT, + PROP_RAW_DOUBLE +} RawPropertyType; + +typedef struct RawArray { + void *array; + RawPropertyType type; + int len; + int stride; +} RawArray; + /* Iterator Utility */ typedef struct EnumPropertyItem { diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index 222b9bc4d29..4098ca70356 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -762,6 +762,42 @@ static char *rna_def_property_end_func(FILE *f, StructRNA *srna, PropertyRNA *pr return func; } +static void rna_set_raw_property(PropertyDefRNA *dp, PropertyRNA *prop) +{ + if(dp->dnapointerlevel != 0) + return; + if(!dp->dnatype || !dp->dnaname || !dp->dnastructname) + return; + + if(strcmp(dp->dnatype, "char") == 0) { + prop->rawtype= PROP_RAW_CHAR; + prop->flag |= PROP_RAW_ACCESS; + } + else if(strcmp(dp->dnatype, "short") == 0) { + prop->rawtype= PROP_RAW_SHORT; + prop->flag |= PROP_RAW_ACCESS; + } + else if(strcmp(dp->dnatype, "int") == 0) { + prop->rawtype= PROP_RAW_INT; + prop->flag |= PROP_RAW_ACCESS; + } + else if(strcmp(dp->dnatype, "float") == 0) { + prop->rawtype= PROP_RAW_FLOAT; + prop->flag |= PROP_RAW_ACCESS; + } + else if(strcmp(dp->dnatype, "double") == 0) { + prop->rawtype= PROP_RAW_DOUBLE; + prop->flag |= PROP_RAW_ACCESS; + } +} + +static void rna_set_raw_offset(FILE *f, StructRNA *srna, PropertyRNA *prop) +{ + PropertyDefRNA *dp= rna_find_struct_property_def(srna, prop); + + fprintf(f, "\toffsetof(%s, %s), %d", dp->dnastructname, dp->dnaname, prop->rawtype); +} + static void rna_def_property_funcs(FILE *f, StructRNA *srna, PropertyDefRNA *dp) { PropertyRNA *prop; @@ -773,6 +809,9 @@ static void rna_def_property_funcs(FILE *f, StructRNA *srna, PropertyDefRNA *dp) BooleanPropertyRNA *bprop= (BooleanPropertyRNA*)prop; if(!prop->arraylength) { + if(!bprop->get && !bprop->set && !dp->booleanbit) + rna_set_raw_property(dp, prop); + bprop->get= (void*)rna_def_property_get_func(f, srna, prop, dp, (char*)bprop->get); bprop->set= (void*)rna_def_property_set_func(f, srna, prop, dp, (char*)bprop->set); } @@ -786,10 +825,16 @@ static void rna_def_property_funcs(FILE *f, StructRNA *srna, PropertyDefRNA *dp) IntPropertyRNA *iprop= (IntPropertyRNA*)prop; if(!prop->arraylength) { + if(!iprop->get && !iprop->set) + rna_set_raw_property(dp, prop); + iprop->get= (void*)rna_def_property_get_func(f, srna, prop, dp, (char*)iprop->get); iprop->set= (void*)rna_def_property_set_func(f, srna, prop, dp, (char*)iprop->set); } else { + if(!iprop->getarray && !iprop->setarray) + rna_set_raw_property(dp, prop); + iprop->getarray= (void*)rna_def_property_get_func(f, srna, prop, dp, (char*)iprop->getarray); iprop->setarray= (void*)rna_def_property_set_func(f, srna, prop, dp, (char*)iprop->setarray); } @@ -799,10 +844,16 @@ static void rna_def_property_funcs(FILE *f, StructRNA *srna, PropertyDefRNA *dp) FloatPropertyRNA *fprop= (FloatPropertyRNA*)prop; if(!prop->arraylength) { + if(!fprop->get && !fprop->set) + rna_set_raw_property(dp, prop); + fprop->get= (void*)rna_def_property_get_func(f, srna, prop, dp, (char*)fprop->get); fprop->set= (void*)rna_def_property_set_func(f, srna, prop, dp, (char*)fprop->set); } else { + if(!fprop->getarray && !fprop->setarray) + rna_set_raw_property(dp, prop); + fprop->getarray= (void*)rna_def_property_get_func(f, srna, prop, dp, (char*)fprop->getarray); fprop->setarray= (void*)rna_def_property_set_func(f, srna, prop, dp, (char*)fprop->setarray); } @@ -841,6 +892,13 @@ static void rna_def_property_funcs(FILE *f, StructRNA *srna, PropertyDefRNA *dp) else if(dp->dnalengthname || dp->dnalengthfixed) cprop->length= (void*)rna_def_property_length_func(f, srna, prop, dp, (char*)cprop->length); + /* test if we can allow raw array access, if it is using our standard + * array get/next function, we can be sure it is an actual array */ + if(cprop->next && cprop->get) + if(strcmp((char*)cprop->next, "rna_iterator_array_next") == 0 && + strcmp((char*)cprop->get, "rna_iterator_array_get") == 0) + prop->flag |= PROP_RAW_ARRAY; + cprop->get= (void*)rna_def_property_get_func(f, srna, prop, dp, (char*)cprop->get); cprop->begin= (void*)rna_def_property_begin_func(f, srna, prop, dp, (char*)cprop->begin); cprop->next= (void*)rna_def_property_next_func(f, srna, prop, dp, (char*)cprop->next); @@ -1538,7 +1596,7 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr DefRNA.error= 1; } break; - } + } case PROP_BOOLEAN: { BooleanPropertyRNA *bprop= (BooleanPropertyRNA*)prop; unsigned int i; @@ -1558,7 +1616,7 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr fprintf(f, "};\n\n"); } break; - } + } case PROP_INT: { IntPropertyRNA *iprop= (IntPropertyRNA*)prop; unsigned int i; @@ -1578,7 +1636,7 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr fprintf(f, "};\n\n"); } break; - } + } case PROP_FLOAT: { FloatPropertyRNA *fprop= (FloatPropertyRNA*)prop; unsigned int i; @@ -1598,7 +1656,7 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr fprintf(f, "};\n\n"); } break; - } + } default: break; } @@ -1613,10 +1671,14 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr rna_print_c_string(f, prop->identifier); fprintf(f, ", %d, ", prop->flag); rna_print_c_string(f, prop->name); fprintf(f, ",\n\t"); - rna_print_c_string(f, prop->description); fprintf(f, ",\n"); - fprintf(f, "%d, ", prop->icon); + rna_print_c_string(f, prop->description); fprintf(f, ",\n\t"); + fprintf(f, "%d,\n", prop->icon); fprintf(f, "\t%s, %s, %d,\n", rna_property_typename(prop->type), rna_property_subtypename(prop->subtype), prop->arraylength); - fprintf(f, "\t%s, %d, %s},\n", rna_function_string(prop->update), prop->noteflag, rna_function_string(prop->editable)); + fprintf(f, "\t%s, %d, %s,\n", rna_function_string(prop->update), prop->noteflag, rna_function_string(prop->editable)); + + if(prop->flag & PROP_RAW_ACCESS) rna_set_raw_offset(f, srna, prop); + else fprintf(f, "\t0, 0"); + fprintf(f, "},\n"); switch(prop->type) { case PROP_BOOLEAN: { @@ -1625,7 +1687,7 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr if(prop->arraylength) fprintf(f, "rna_%s%s_%s_default\n", srna->identifier, strnest, prop->identifier); else fprintf(f, "NULL\n"); break; - } + } case PROP_INT: { IntPropertyRNA *iprop= (IntPropertyRNA*)prop; fprintf(f, "\t%s, %s, %s, %s, %s,\n\t", rna_function_string(iprop->get), rna_function_string(iprop->set), rna_function_string(iprop->getarray), rna_function_string(iprop->setarray), rna_function_string(iprop->range)); @@ -1638,7 +1700,7 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr if(prop->arraylength) fprintf(f, "rna_%s%s_%s_default\n", srna->identifier, strnest, prop->identifier); else fprintf(f, "NULL\n"); break; - } + } case PROP_FLOAT: { FloatPropertyRNA *fprop= (FloatPropertyRNA*)prop; fprintf(f, "\t%s, %s, %s, %s, %s, ", rna_function_string(fprop->get), rna_function_string(fprop->set), rna_function_string(fprop->getarray), rna_function_string(fprop->setarray), rna_function_string(fprop->range)); @@ -1652,13 +1714,13 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr if(prop->arraylength) fprintf(f, "rna_%s%s_%s_default\n", srna->identifier, strnest, prop->identifier); else fprintf(f, "NULL\n"); break; - } + } case PROP_STRING: { StringPropertyRNA *sprop= (StringPropertyRNA*)prop; fprintf(f, "\t%s, %s, %s, %d, ", rna_function_string(sprop->get), rna_function_string(sprop->length), rna_function_string(sprop->set), sprop->maxlength); rna_print_c_string(f, sprop->defaultvalue); fprintf(f, "\n"); break; - } + } case PROP_ENUM: { EnumPropertyRNA *eprop= (EnumPropertyRNA*)prop; fprintf(f, "\t%s, %s, %s, ", rna_function_string(eprop->get), rna_function_string(eprop->set), rna_function_string(eprop->itemf)); @@ -1668,14 +1730,14 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr fprintf(f, "NULL, "); fprintf(f, "%d, %d\n", eprop->totitem, eprop->defaultvalue); break; - } + } case PROP_POINTER: { PointerPropertyRNA *pprop= (PointerPropertyRNA*)prop; fprintf(f, "\t%s, %s, %s, ", rna_function_string(pprop->get), rna_function_string(pprop->set), rna_function_string(pprop->typef)); if(pprop->type) fprintf(f, "&RNA_%s\n", (char*)pprop->type); else fprintf(f, "NULL\n"); break; - } + } case PROP_COLLECTION: { CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)prop; fprintf(f, "\t%s, %s, %s, %s, %s, %s, %s, ", rna_function_string(cprop->begin), rna_function_string(cprop->next), rna_function_string(cprop->end), rna_function_string(cprop->get), rna_function_string(cprop->length), rna_function_string(cprop->lookupint), rna_function_string(cprop->lookupstring)); @@ -1891,6 +1953,7 @@ static void rna_generate(BlenderRNA *brna, FILE *f, char *filename, char *api_fi fprintf(f, "#include \n"); fprintf(f, "#include \n"); fprintf(f, "#include \n\n"); + fprintf(f, "#include \n\n"); fprintf(f, "#include \"DNA_ID.h\"\n"); diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 7defb0676c6..cc8704dc350 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -1522,6 +1522,323 @@ int RNA_property_collection_lookup_string(PointerRNA *ptr, PropertyRNA *prop, co } } +int RNA_property_collection_raw_array(PointerRNA *ptr, PropertyRNA *prop, PropertyRNA *itemprop, RawArray *array) +{ + CollectionPropertyIterator iter; + ArrayIterator *internal; + char *arrayp; + + if(!(prop->flag & PROP_RAW_ARRAY) || !(itemprop->flag & PROP_RAW_ACCESS)) + return 0; + + RNA_property_collection_begin(ptr, prop, &iter); + + if(iter.valid) { + /* get data from array iterator and item property */ + internal= iter.internal; + arrayp= (iter.valid)? iter.ptr.data: NULL; + + if(internal->skip || !RNA_property_editable(&iter.ptr, itemprop)) { + /* we might skip some items, so it's not a proper array */ + RNA_property_collection_end(&iter); + return 0; + } + + array->array= arrayp + itemprop->rawoffset; + array->stride= internal->itemsize; + array->len= ((char*)internal->endptr - arrayp)/internal->itemsize; + array->type= itemprop->rawtype; + } + else + memset(array, 0, sizeof(RawArray)); + + RNA_property_collection_end(&iter); + + return 1; +} + +#define RAW_GET(dtype, var, raw, a) \ +{ \ + switch(raw.type) { \ + case PROP_RAW_CHAR: var = (dtype)((char*)raw.array)[a]; break; \ + case PROP_RAW_SHORT: var = (dtype)((short*)raw.array)[a]; break; \ + case PROP_RAW_INT: var = (dtype)((int*)raw.array)[a]; break; \ + case PROP_RAW_FLOAT: var = (dtype)((float*)raw.array)[a]; break; \ + case PROP_RAW_DOUBLE: var = (dtype)((double*)raw.array)[a]; break; \ + default: var = (dtype)0; \ + } \ +} + +#define RAW_SET(dtype, raw, a, var) \ +{ \ + switch(raw.type) { \ + case PROP_RAW_CHAR: ((char*)raw.array)[a] = (char)var; break; \ + case PROP_RAW_SHORT: ((short*)raw.array)[a] = (short)var; break; \ + case PROP_RAW_INT: ((int*)raw.array)[a] = (int)var; break; \ + case PROP_RAW_FLOAT: ((float*)raw.array)[a] = (float)var; break; \ + case PROP_RAW_DOUBLE: ((double*)raw.array)[a] = (double)var; break; \ + } \ +} + +int RNA_raw_type_sizeof(RawPropertyType type) +{ + switch(type) { + case PROP_RAW_CHAR: return sizeof(char); + case PROP_RAW_SHORT: return sizeof(short); + case PROP_RAW_INT: return sizeof(int); + case PROP_RAW_FLOAT: return sizeof(float); + case PROP_RAW_DOUBLE: return sizeof(double); + default: return 0; + } +} + +static int rna_raw_access(ReportList *reports, PointerRNA *ptr, PropertyRNA *prop, char *propname, void *inarray, RawPropertyType intype, int inlen, int set) +{ + StructRNA *ptype; + PointerRNA itemptr; + PropertyRNA *itemprop, *iprop; + PropertyType itemtype; + RawArray in; + int itemlen= 0; + + /* initialize in array, stride assumed 0 in following code */ + in.array= inarray; + in.type= intype; + in.len= inlen; + in.stride= 0; + + ptype= RNA_property_pointer_type(ptr, prop); + + /* try to get item property pointer */ + RNA_pointer_create(NULL, ptype, NULL, &itemptr); + itemprop= RNA_struct_find_property(&itemptr, propname); + + if(itemprop) { + /* we have item property pointer */ + RawArray out; + + /* check type */ + itemtype= RNA_property_type(itemprop); + + if(!ELEM3(itemtype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) { + BKE_report(reports, RPT_ERROR, "Only boolean, int and float properties supported."); + return 0; + } + + /* check item array */ + itemlen= RNA_property_array_length(itemprop); + + /* try to access as raw array */ + if(RNA_property_collection_raw_array(ptr, prop, itemprop, &out)) { + if(in.len != itemlen*out.len) { + BKE_reportf(reports, RPT_ERROR, "Array length mismatch (expected %d, got %d).", out.len*itemlen, in.len); + return 0; + } + + /* matching raw types */ + if(out.type == in.type) { + void *inp= in.array; + void *outp= out.array; + int a, size; + + itemlen= (itemlen == 0)? 1: itemlen; + size= RNA_raw_type_sizeof(out.type) * itemlen; + + for(a=0; a in.len) { + BKE_reportf(reports, RPT_ERROR, "Array length mismatch (got %d, expected more).", in.len); + err= 1; + break; + } + + if(itemlen == 0) { + /* handle conversions */ + if(set) { + switch(itemtype) { + case PROP_BOOLEAN: { + int b; + RAW_GET(int, b, in, a); + RNA_property_boolean_set(&itemptr, iprop, b); + break; + } + case PROP_INT: { + int i; + RAW_GET(int, i, in, a); + RNA_property_int_set(&itemptr, iprop, i); + break; + } + case PROP_FLOAT: { + float f; + RAW_GET(float, f, in, a); + RNA_property_float_set(&itemptr, iprop, f); + break; + } + default: + break; + } + } + else { + switch(itemtype) { + case PROP_BOOLEAN: { + int b= RNA_property_boolean_get(&itemptr, iprop); + RAW_SET(int, in, a, b); + break; + } + case PROP_INT: { + int i= RNA_property_int_get(&itemptr, iprop); + RAW_SET(int, in, a, i); + break; + } + case PROP_FLOAT: { + float f= RNA_property_float_get(&itemptr, iprop); + RAW_SET(float, in, a, f); + break; + } + default: + break; + } + } + a++; + } + else { + /* allocate temporary array if needed */ + if(tmparray && tmplen != itemlen) { + MEM_freeN(tmparray); + tmparray= NULL; + } + if(!tmparray) { + tmparray= MEM_callocN(sizeof(float)*itemlen, "RNA tmparray\n"); + tmplen= itemlen; + } + + /* handle conversions */ + if(set) { + switch(itemtype) { + case PROP_BOOLEAN: { + for(j=0; jrawtype; +} + +int RNA_property_collection_raw_get(ReportList *reports, PointerRNA *ptr, PropertyRNA *prop, char *propname, void *array, RawPropertyType type, int len) +{ + return rna_raw_access(reports, ptr, prop, propname, array, type, len, 0); +} + +int RNA_property_collection_raw_set(ReportList *reports, PointerRNA *ptr, PropertyRNA *prop, char *propname, void *array, RawPropertyType type, int len) +{ + return rna_raw_access(reports, ptr, prop, propname, array, type, len, 1); +} + /* Standard iterator functions */ void rna_iterator_listbase_begin(CollectionPropertyIterator *iter, ListBase *lb, IteratorSkipFunc skip) @@ -2733,23 +3050,46 @@ static int rna_function_parameter_parse(PointerRNA *ptr, PropertyRNA *prop, Prop if(prop->flag & PROP_RNAPTR) { *((PointerRNA*)dest)= *((PointerRNA*)src); + break; + } + + if (ptype!=srna && !RNA_struct_is_a(srna, ptype)) { + fprintf(stderr, "%s.%s: wrong type for parameter %s, an object of type %s was expected, passed an object of type %s\n", tid, fid, pid, RNA_struct_identifier(ptype), RNA_struct_identifier(srna)); + return -1; } - else if (ptype!=srna) { - if (!RNA_struct_is_a(srna, ptype)) { - fprintf(stderr, "%s.%s: wrong type for parameter %s, an object of type %s was expected, passed an object of type %s\n", tid, fid, pid, RNA_struct_identifier(ptype), RNA_struct_identifier(ptype)); - return -1; - } - - *((void**)dest)= *((void**)src); - } + + *((void**)dest)= *((void**)src); break; } case PROP_COLLECTION: { - /* XXX collections are not supported yet */ - fprintf(stderr, "%s.%s: for parameter %s, collections are not supported yet\n", tid, fid, pid); - return -1; + StructRNA *ptype; + ListBase *lb, *clb; + Link *link; + CollectionPointerLink *clink; + + if (ftype!='C') { + fprintf(stderr, "%s.%s: wrong type for parameter %s, a collection was expected\n", tid, fid, pid); + return -1; + } + + lb= (ListBase *)src; + clb= (ListBase *)dest; + ptype= RNA_property_pointer_type(ptr, prop); + + if (ptype!=srna && !RNA_struct_is_a(srna, ptype)) { + fprintf(stderr, "%s.%s: wrong type for parameter %s, a collection of objects of type %s was expected, passed a collection of objects of type %s\n", tid, fid, pid, RNA_struct_identifier(ptype), RNA_struct_identifier(srna)); + return -1; + } + + for (link= lb->first; link; link= link->next) { + clink= MEM_callocN(sizeof(CollectionPointerLink), "CCollectionPointerLink"); + RNA_pointer_create(NULL, srna, link, &clink->ptr); + BLI_addtail(clb, clink); + } + + break; } default: { @@ -2847,6 +3187,13 @@ int RNA_function_call_direct_va(bContext *C, ReportList *reports, PointerRNA *pt err= rna_function_parameter_parse(&funcptr, parm, type, ftype, len, iter.data, &arg, srna, tid, fid, pid); break; } + case PROP_COLLECTION: + { + StructRNA *srna= va_arg(args, StructRNA*); + ListBase *arg= va_arg(args, ListBase*); + err= rna_function_parameter_parse(&funcptr, parm, type, ftype, len, iter.data, &arg, srna, tid, fid, pid); + break; + } default: { /* handle errors */ @@ -2904,6 +3251,13 @@ int RNA_function_call_direct_va(bContext *C, ReportList *reports, PointerRNA *pt err= rna_function_parameter_parse(&funcptr, parm, type, ftype, len, arg, retdata, srna, tid, fid, pid); break; } + case PROP_COLLECTION: + { + StructRNA *srna= va_arg(args, StructRNA*); + ListBase **arg= va_arg(args, ListBase**); + err= rna_function_parameter_parse(&funcptr, parm, type, ftype, len, arg, retdata, srna, tid, fid, pid); + break; + } default: { /* handle errors */ @@ -2932,3 +3286,4 @@ int RNA_function_call_direct_va_lookup(bContext *C, ReportList *reports, Pointer return 0; } + diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index 90617d01833..7355261c5aa 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -184,6 +184,10 @@ void rna_def_brush(BlenderRNA *brna) prop= RNA_def_property(srna, "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); + 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."); /* not exposed in the interface yet prop= RNA_def_property(srna, "fixed_tex", PROP_BOOLEAN, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index 8200a21f4ac..5c4b6a95524 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -535,10 +535,8 @@ 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."); - RNA_def_struct_sdna(srna, "bConstraint"); - prop= RNA_def_property(srna, "head_tail", PROP_FLOAT, PROP_PERCENTAGE); - RNA_def_property_float_sdna(prop, NULL, "headtail"); + 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"); diff --git a/source/blender/makesrna/intern/rna_context.c b/source/blender/makesrna/intern/rna_context.c index 07a50235733..7fa27348002 100644 --- a/source/blender/makesrna/intern/rna_context.c +++ b/source/blender/makesrna/intern/rna_context.c @@ -40,11 +40,11 @@ static PointerRNA rna_Context_manager_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_WindowManager, CTX_wm_manager(C)); } -/*static PointerRNA rna_Context_window_get(PointerRNA *ptr) +static PointerRNA rna_Context_window_get(PointerRNA *ptr) { bContext *C= (bContext*)ptr->data; return rna_pointer_inherit_refine(ptr, &RNA_Window, CTX_wm_window(C)); -}*/ +} static PointerRNA rna_Context_screen_get(PointerRNA *ptr) { @@ -96,6 +96,12 @@ static PointerRNA rna_Context_scene_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_Scene, CTX_data_scene(C)); } +static PointerRNA rna_Context_tool_settings_get(PointerRNA *ptr) +{ + bContext *C= (bContext*)ptr->data; + return rna_pointer_inherit_refine(ptr, &RNA_ToolSettings, CTX_data_tool_settings(C)); +} + #else void RNA_def_context(BlenderRNA *brna) @@ -113,10 +119,10 @@ void RNA_def_context(BlenderRNA *brna) RNA_def_property_struct_type(prop, "WindowManager"); RNA_def_property_pointer_funcs(prop, "rna_Context_manager_get", NULL, NULL); - /* prop= RNA_def_property(srna, "window", PROP_POINTER, PROP_NONE); + prop= RNA_def_property(srna, "window", PROP_POINTER, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_struct_type(prop, "Window"); - RNA_def_property_pointer_funcs(prop, "rna_Context_window_get", NULL, NULL); */ + RNA_def_property_pointer_funcs(prop, "rna_Context_window_get", NULL, NULL); prop= RNA_def_property(srna, "screen", PROP_POINTER, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); @@ -153,6 +159,12 @@ void RNA_def_context(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_struct_type(prop, "Scene"); RNA_def_property_pointer_funcs(prop, "rna_Context_scene_get", NULL, NULL); + + prop= RNA_def_property(srna, "tool_settings", PROP_POINTER, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_struct_type(prop, "ToolSettings"); + RNA_def_property_pointer_funcs(prop, "rna_Context_tool_settings_get", NULL, NULL); + } #endif diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c index bd449acc050..715f03bb3f1 100644 --- a/source/blender/makesrna/intern/rna_define.c +++ b/source/blender/makesrna/intern/rna_define.c @@ -112,7 +112,7 @@ StructDefRNA *rna_find_struct_def(StructRNA *srna) return NULL; } -PropertyDefRNA *rna_find_struct_property_def(PropertyRNA *prop) +PropertyDefRNA *rna_find_struct_property_def(StructRNA *srna, PropertyRNA *prop) { StructDefRNA *dsrna; PropertyDefRNA *dprop; @@ -123,7 +123,7 @@ PropertyDefRNA *rna_find_struct_property_def(PropertyRNA *prop) return NULL; } - dsrna= rna_find_struct_def(DefRNA.laststruct); + dsrna= rna_find_struct_def(srna); dprop= dsrna->cont.properties.last; for (; dprop; dprop= dprop->prev) if (dprop->prop==prop) @@ -150,7 +150,7 @@ PropertyDefRNA *rna_find_property_def(PropertyRNA *prop) return NULL; } - dprop= rna_find_struct_property_def(prop); + dprop= rna_find_struct_property_def(DefRNA.laststruct, prop); if (dprop) return dprop; @@ -1311,7 +1311,7 @@ static PropertyDefRNA *rna_def_property_sdna(PropertyRNA *prop, const char *stru StructDefRNA *ds; PropertyDefRNA *dp; - dp= rna_find_struct_property_def(prop); + dp= rna_find_struct_property_def(DefRNA.laststruct, prop); if (dp==NULL) return NULL; ds= rna_find_struct_def((StructRNA*)dp->cont); @@ -1371,7 +1371,7 @@ void RNA_def_property_boolean_negative_sdna(PropertyRNA *prop, const char *struc RNA_def_property_boolean_sdna(prop, structname, propname, booleanbit); - dp= rna_find_struct_property_def(prop); + dp= rna_find_struct_property_def(DefRNA.laststruct, prop); if(dp) dp->booleannegative= 1; @@ -1468,7 +1468,7 @@ void RNA_def_property_enum_bitflag_sdna(PropertyRNA *prop, const char *structnam RNA_def_property_enum_sdna(prop, structname, propname); - dp= rna_find_struct_property_def(prop); + dp= rna_find_struct_property_def(DefRNA.laststruct, prop); if(dp) dp->enumbitflags= 1; @@ -2249,7 +2249,6 @@ int rna_parameter_size(PropertyRNA *parm) #endif } case PROP_COLLECTION: - /* XXX does not work yet */ return sizeof(ListBase); } } diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c index 4a6fdf5a734..c74e46c17da 100644 --- a/source/blender/makesrna/intern/rna_image.c +++ b/source/blender/makesrna/intern/rna_image.c @@ -39,6 +39,8 @@ #ifdef RNA_RUNTIME +#include "IMB_imbuf_types.h" + static void rna_Image_animated_update(bContext *C, PointerRNA *ptr) { Image *ima= (Image*)ptr->data; @@ -52,6 +54,18 @@ static void rna_Image_animated_update(bContext *C, PointerRNA *ptr) } } +static int rna_Image_dirty_get(PointerRNA *ptr) +{ + Image *ima= (Image*)ptr->data; + ImBuf *ibuf; + + for(ibuf=ima->ibufs.first; ibuf; ibuf=ibuf->next) + if(ibuf->userflags & IB_BITMAPDIRTY) + return 1; + + return 0; +} + #else static void rna_def_imageuser(BlenderRNA *brna) @@ -174,6 +188,11 @@ static void rna_def_image(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Premultiply", "Convert RGB from key alpha to premultiplied alpha."); RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL); + prop= RNA_def_property(srna, "dirty", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_funcs(prop, "rna_Image_dirty_get", NULL); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Dirty", "Image has changed and is not saved."); + /* generated image (image_generated_change_cb) */ prop= RNA_def_property(srna, "generated_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "gen_type"); diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h index c2f2e1d519f..5b8e7c76636 100644 --- a/source/blender/makesrna/intern/rna_internal.h +++ b/source/blender/makesrna/intern/rna_internal.h @@ -256,6 +256,7 @@ void rna_freelistN(struct ListBase *listbase); StructDefRNA *rna_find_struct_def(StructRNA *srna); FunctionDefRNA *rna_find_function_def(FunctionRNA *func); PropertyDefRNA *rna_find_parameter_def(PropertyRNA *parm); +PropertyDefRNA *rna_find_struct_property_def(StructRNA *srna, PropertyRNA *prop); /* Pointer Handling */ diff --git a/source/blender/makesrna/intern/rna_internal_types.h b/source/blender/makesrna/intern/rna_internal_types.h index 8bae21cca2b..401b430ebc9 100644 --- a/source/blender/makesrna/intern/rna_internal_types.h +++ b/source/blender/makesrna/intern/rna_internal_types.h @@ -146,6 +146,10 @@ struct PropertyRNA { /* callback for testing if editable/evaluated */ EditableFunc editable; + + /* raw access */ + int rawoffset; + RawPropertyType rawtype; }; /* Property Types */ diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index e56760f5ca3..39fa6f36f23 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -34,10 +34,37 @@ #include "DNA_meshdata_types.h" #include "DNA_object_types.h" -#include "BKE_customdata.h" - #ifdef RNA_RUNTIME +#include "DNA_scene_types.h" + +#include "BLI_editVert.h" + +#include "BKE_customdata.h" +#include "BKE_depsgraph.h" +#include "BKE_main.h" +#include "BKE_mesh.h" +#include "BKE_utildefines.h" + +#include "WM_api.h" +#include "WM_types.h" + +static void rna_Mesh_update_data(bContext *C, PointerRNA *ptr) +{ + Main *bmain= CTX_data_main(C); + Scene *scene= CTX_data_scene(C); + ID *id= ptr->id.data; + Object *ob; + + for(ob=bmain->object.first; ob; ob= ob->id.next) { + if(ob->data == id) { + /* XXX this will loop over all objects again (slow) */ + DAG_object_flush_update(scene, ob, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob); + } + } +} + static void rna_MeshVertex_normal_get(PointerRNA *ptr, float *value) { MVert *mvert= (MVert*)ptr->data; @@ -183,13 +210,19 @@ static void rna_MeshFace_material_index_range(PointerRNA *ptr, int *min, int *ma *max= me->totcol-1; } +static CustomData *rna_mesh_fdata(Mesh *me) +{ + return (me->edit_mesh)? &me->edit_mesh->fdata: &me->fdata; +} + static int rna_CustomDataLayer_length(PointerRNA *ptr, int type) { Mesh *me= (Mesh*)ptr->id.data; + CustomData *fdata= rna_mesh_fdata(me); CustomDataLayer *layer; int i, length= 0; - for(layer=me->fdata.layers, i=0; ifdata.totlayer; layer++, i++) + for(layer=fdata->layers, i=0; itotlayer; layer++, i++) if(layer->type == type) length++; @@ -199,64 +232,96 @@ static int rna_CustomDataLayer_length(PointerRNA *ptr, int type) static int rna_CustomDataLayer_active_get(PointerRNA *ptr, int type, int render) { Mesh *me= (Mesh*)ptr->id.data; - int n= ((CustomDataLayer*)ptr->data) - me->fdata.layers; + CustomData *fdata= rna_mesh_fdata(me); + int n= ((CustomDataLayer*)ptr->data) - fdata->layers; - if(render) return (n == CustomData_get_render_layer_index(&me->fdata, type)); - else return (n == CustomData_get_active_layer_index(&me->fdata, type)); + if(render) return (n == CustomData_get_render_layer_index(fdata, type)); + else return (n == CustomData_get_active_layer_index(fdata, type)); } static void rna_CustomDataLayer_active_set(PointerRNA *ptr, int value, int type, int render) { Mesh *me= (Mesh*)ptr->id.data; - int n= ((CustomDataLayer*)ptr->data) - me->fdata.layers; + CustomData *fdata= rna_mesh_fdata(me); + int n= ((CustomDataLayer*)ptr->data) - fdata->layers; if(value == 0) return; - if(render) CustomData_set_layer_render_index(&me->fdata, type, n); - else CustomData_set_layer_active_index(&me->fdata, type, n); + if(render) CustomData_set_layer_render_index(fdata, type, n); + else CustomData_set_layer_active_index(fdata, type, n); } -static int rna_uv_layer_check(CollectionPropertyIterator *iter, void *data) +static int rna_uv_texture_check(CollectionPropertyIterator *iter, void *data) { CustomDataLayer *layer= (CustomDataLayer*)data; return (layer->type != CD_MTFACE); } -static void rna_Mesh_uv_layers_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) +static void rna_Mesh_uv_textures_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { Mesh *me= (Mesh*)ptr->data; - rna_iterator_array_begin(iter, (void*)me->fdata.layers, sizeof(CustomDataLayer), me->fdata.totlayer, rna_uv_layer_check); + CustomData *fdata= rna_mesh_fdata(me); + rna_iterator_array_begin(iter, (void*)fdata->layers, sizeof(CustomDataLayer), fdata->totlayer, rna_uv_texture_check); } -static int rna_Mesh_uv_layers_length(PointerRNA *ptr) +static int rna_Mesh_uv_textures_length(PointerRNA *ptr) { return rna_CustomDataLayer_length(ptr, CD_MTFACE); } -static PointerRNA rna_Mesh_active_uv_layer_get(PointerRNA *ptr) +static PointerRNA rna_Mesh_active_uv_texture_get(PointerRNA *ptr) { Mesh *me= (Mesh*)ptr->data; - int index= CustomData_get_active_layer_index(&me->fdata, CD_MTFACE); - CustomDataLayer *cdl= (index == -1)? NULL: &me->fdata.layers[index]; + CustomData *fdata= rna_mesh_fdata(me); + int index= CustomData_get_active_layer_index(fdata, CD_MTFACE); + CustomDataLayer *cdl= (index == -1)? NULL: &fdata->layers[index]; return rna_pointer_inherit_refine(ptr, &RNA_MeshTextureFaceLayer, cdl); } -static void rna_Mesh_active_uv_layer_set(PointerRNA *ptr, PointerRNA value) +static void rna_Mesh_active_uv_texture_set(PointerRNA *ptr, PointerRNA value) { Mesh *me= (Mesh*)ptr->data; + CustomData *fdata= rna_mesh_fdata(me); CustomDataLayer *cdl; int a; - for(cdl=me->fdata.layers, a=0; afdata.totlayer; cdl++, a++) { + for(cdl=fdata->layers, a=0; atotlayer; cdl++, a++) { if(value.data == cdl) { - CustomData_set_layer_active_index(&me->fdata, CD_MTFACE, a); + CustomData_set_layer_active_index(fdata, CD_MTFACE, a); + mesh_update_customdata_pointers(me); return; } } } +static int rna_Mesh_active_uv_texture_index_get(PointerRNA *ptr) +{ + Mesh *me= (Mesh*)ptr->data; + CustomData *fdata= rna_mesh_fdata(me); + return CustomData_get_active_layer(fdata, CD_MTFACE); +} + +static void rna_Mesh_active_uv_texture_index_set(PointerRNA *ptr, int value) +{ + Mesh *me= (Mesh*)ptr->data; + CustomData *fdata= rna_mesh_fdata(me); + + CustomData_set_layer_active(fdata, CD_MTFACE, value); + mesh_update_customdata_pointers(me); +} + +static void rna_Mesh_active_uv_texture_index_range(PointerRNA *ptr, int *min, int *max) +{ + Mesh *me= (Mesh*)ptr->data; + CustomData *fdata= rna_mesh_fdata(me); + + *min= 0; + *max= CustomData_number_of_layers(fdata, CD_MTFACE)-1; + *max= MAX2(0, *max); +} + static void rna_MeshTextureFace_uv1_get(PointerRNA *ptr, float *values) { MTFace *mtface= (MTFace*)ptr->data; @@ -354,46 +419,84 @@ static void rna_MeshTextureFaceLayer_active_set(PointerRNA *ptr, int value) rna_CustomDataLayer_active_set(ptr, value, CD_MTFACE, 0); } -static int rna_vcol_layer_check(CollectionPropertyIterator *iter, void *data) +static void rna_MeshTextureFaceLayer_name_set(PointerRNA *ptr, const char *value) +{ + Mesh *me= (Mesh*)ptr->id.data; + CustomDataLayer *cdl= (CustomDataLayer*)ptr->data; + BLI_strncpy(cdl->name, value, sizeof(cdl->name)); + CustomData_set_layer_unique_name(&me->fdata, cdl - me->fdata.layers); +} + +static int rna_vertex_color_check(CollectionPropertyIterator *iter, void *data) { CustomDataLayer *layer= (CustomDataLayer*)data; return (layer->type != CD_MCOL); } -static void rna_Mesh_vcol_layers_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) +static void rna_Mesh_vertex_colors_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { Mesh *me= (Mesh*)ptr->data; - rna_iterator_array_begin(iter, (void*)me->fdata.layers, sizeof(CustomDataLayer), me->fdata.totlayer, rna_vcol_layer_check); + CustomData *fdata= rna_mesh_fdata(me); + rna_iterator_array_begin(iter, (void*)fdata->layers, sizeof(CustomDataLayer), fdata->totlayer, rna_vertex_color_check); } -static int rna_Mesh_vcol_layers_length(PointerRNA *ptr) +static int rna_Mesh_vertex_colors_length(PointerRNA *ptr) { return rna_CustomDataLayer_length(ptr, CD_MCOL); } -static PointerRNA rna_Mesh_active_vcol_layer_get(PointerRNA *ptr) +static PointerRNA rna_Mesh_active_vertex_color_get(PointerRNA *ptr) { Mesh *me= (Mesh*)ptr->data; - int index= CustomData_get_active_layer_index(&me->fdata, CD_MCOL); - CustomDataLayer *cdl= (index == -1)? NULL: &me->fdata.layers[index]; + CustomData *fdata= rna_mesh_fdata(me); + int index= CustomData_get_active_layer_index(fdata, CD_MCOL); + CustomDataLayer *cdl= (index == -1)? NULL: &fdata->layers[index]; return rna_pointer_inherit_refine(ptr, &RNA_MeshColorLayer, cdl); } -static void rna_Mesh_active_vcol_layer_set(PointerRNA *ptr, PointerRNA value) +static void rna_Mesh_active_vertex_color_set(PointerRNA *ptr, PointerRNA value) { Mesh *me= (Mesh*)ptr->data; + CustomData *fdata= rna_mesh_fdata(me); CustomDataLayer *cdl; int a; - for(cdl=me->fdata.layers, a=0; afdata.totlayer; cdl++, a++) { + for(cdl=fdata->layers, a=0; atotlayer; cdl++, a++) { if(value.data == cdl) { - CustomData_set_layer_active_index(&me->fdata, CD_MCOL, a); + CustomData_set_layer_active_index(fdata, CD_MCOL, a); + mesh_update_customdata_pointers(me); return; } } } +static int rna_Mesh_active_vertex_color_index_get(PointerRNA *ptr) +{ + Mesh *me= (Mesh*)ptr->data; + CustomData *fdata= rna_mesh_fdata(me); + return CustomData_get_active_layer(fdata, CD_MCOL); +} + +static void rna_Mesh_active_vertex_color_index_set(PointerRNA *ptr, int value) +{ + Mesh *me= (Mesh*)ptr->data; + CustomData *fdata= rna_mesh_fdata(me); + + CustomData_set_layer_active(fdata, CD_MCOL, value); + mesh_update_customdata_pointers(me); +} + +static void rna_Mesh_active_vertex_color_index_range(PointerRNA *ptr, int *min, int *max) +{ + Mesh *me= (Mesh*)ptr->data; + CustomData *fdata= rna_mesh_fdata(me); + + *min= 0; + *max= CustomData_number_of_layers(fdata, CD_MCOL)-1; + *max= MAX2(0, *max); +} + static void rna_MeshColorLayer_data_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { Mesh *me= (Mesh*)ptr->id.data; @@ -427,6 +530,14 @@ static void rna_MeshColorLayer_active_set(PointerRNA *ptr, int value) rna_CustomDataLayer_active_set(ptr, value, CD_MCOL, 0); } +static void rna_MeshColorLayer_name_set(PointerRNA *ptr, const char *value) +{ + Mesh *me= (Mesh*)ptr->id.data; + CustomDataLayer *cdl= (CustomDataLayer*)ptr->data; + BLI_strncpy(cdl->name, value, sizeof(cdl->name)); + CustomData_set_layer_unique_name(&me->fdata, cdl - me->fdata.layers); +} + static void rna_MeshFloatPropertyLayer_data_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { Mesh *me= (Mesh*)ptr->id.data; @@ -449,7 +560,8 @@ static int rna_float_layer_check(CollectionPropertyIterator *iter, void *data) static void rna_Mesh_float_layers_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { Mesh *me= (Mesh*)ptr->data; - rna_iterator_array_begin(iter, (void*)me->fdata.layers, sizeof(CustomDataLayer), me->fdata.totlayer, rna_float_layer_check); + CustomData *fdata= rna_mesh_fdata(me); + rna_iterator_array_begin(iter, (void*)fdata->layers, sizeof(CustomDataLayer), fdata->totlayer, rna_float_layer_check); } static int rna_Mesh_float_layers_length(PointerRNA *ptr) @@ -479,7 +591,8 @@ static int rna_MeshIntPropertyLayer_data_length(PointerRNA *ptr) static void rna_Mesh_int_layers_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { Mesh *me= (Mesh*)ptr->data; - rna_iterator_array_begin(iter, (void*)me->fdata.layers, sizeof(CustomDataLayer), me->fdata.totlayer, rna_int_layer_check); + CustomData *fdata= rna_mesh_fdata(me); + rna_iterator_array_begin(iter, (void*)fdata->layers, sizeof(CustomDataLayer), fdata->totlayer, rna_int_layer_check); } static int rna_Mesh_int_layers_length(PointerRNA *ptr) @@ -509,7 +622,8 @@ static int rna_MeshStringPropertyLayer_data_length(PointerRNA *ptr) static void rna_Mesh_string_layers_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { Mesh *me= (Mesh*)ptr->data; - rna_iterator_array_begin(iter, (void*)me->fdata.layers, sizeof(CustomDataLayer), me->fdata.totlayer, rna_string_layer_check); + CustomData *fdata= rna_mesh_fdata(me); + rna_iterator_array_begin(iter, (void*)fdata->layers, sizeof(CustomDataLayer), fdata->totlayer, rna_string_layer_check); } static int rna_Mesh_string_layers_length(PointerRNA *ptr) @@ -568,17 +682,18 @@ static char *rna_MeshVertex_path(PointerRNA *ptr) static char *rna_MeshTextureFaceLayer_path(PointerRNA *ptr) { - return BLI_sprintfN("uv_layers[%s]", ((CustomDataLayer*)ptr->data)->name); + return BLI_sprintfN("uv_textures[%s]", ((CustomDataLayer*)ptr->data)->name); } static char *rna_CustomDataData_path(PointerRNA *ptr, char *collection, int type) { Mesh *me= (Mesh*)ptr->id.data; + CustomData *fdata= rna_mesh_fdata(me); CustomDataLayer *cdl; int a; size_t b; - for(cdl=me->fdata.layers, a=0; afdata.totlayer; cdl++, a++) { + for(cdl=fdata->layers, a=0; atotlayer; cdl++, a++) { if(cdl->type == type) { b= ((char*)ptr->data - ((char*)cdl->data))/CustomData_sizeof(type); if(b >= 0 && b < me->totface) @@ -591,17 +706,17 @@ static char *rna_CustomDataData_path(PointerRNA *ptr, char *collection, int type static char *rna_MeshTextureFace_path(PointerRNA *ptr) { - return rna_CustomDataData_path(ptr, "uv_layers", CD_MTFACE); + return rna_CustomDataData_path(ptr, "uv_textures", CD_MTFACE); } static char *rna_MeshColorLayer_path(PointerRNA *ptr) { - return BLI_sprintfN("vcol_layers[%s]", ((CustomDataLayer*)ptr->data)->name); + return BLI_sprintfN("vertex_colors[%s]", ((CustomDataLayer*)ptr->data)->name); } static char *rna_MeshColor_path(PointerRNA *ptr) { - return rna_CustomDataData_path(ptr, "vcol_layers", CD_MCOL); + return rna_CustomDataData_path(ptr, "vertex_colors", CD_MCOL); } static char *rna_MeshSticky_path(PointerRNA *ptr) @@ -716,8 +831,8 @@ static void rna_def_medge(BlenderRNA *brna) prop= RNA_def_property(srna, "verts", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "v1"); RNA_def_property_array(prop, 2); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Vertices", "Vertex indices"); + // XXX allows creating invalid meshes prop= RNA_def_property(srna, "crease", PROP_FLOAT, PROP_NONE); RNA_def_property_float_funcs(prop, "rna_MEdge_crease_get", "rna_MEdge_crease_set", NULL); @@ -758,8 +873,8 @@ static void rna_def_mface(BlenderRNA *brna) prop= RNA_def_property(srna, "verts", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "v1"); RNA_def_property_array(prop, 4); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Vertices", "Vertex indices"); + // XXX allows creating invalid meshes prop= RNA_def_property(srna, "material_index", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "mat_nr"); @@ -798,6 +913,7 @@ static void rna_def_mtface(BlenderRNA *brna) prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); RNA_def_struct_name_property(srna, prop); + RNA_def_property_string_funcs(prop, NULL, NULL, "rna_MeshTextureFaceLayer_name_set"); RNA_def_property_ui_text(prop, "Name", ""); prop= RNA_def_property(srna, "active", PROP_BOOLEAN, PROP_NONE); @@ -935,6 +1051,7 @@ static void rna_def_mcol(BlenderRNA *brna) prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); RNA_def_struct_name_property(srna, prop); + RNA_def_property_string_funcs(prop, NULL, NULL, "rna_MeshColorLayer_name_set"); RNA_def_property_ui_text(prop, "Name", ""); prop= RNA_def_property(srna, "active", PROP_BOOLEAN, PROP_NONE); @@ -1104,7 +1221,6 @@ static void rna_def_mesh(BlenderRNA *brna) RNA_def_property_collection_sdna(prop, NULL, "mvert", "totvert"); RNA_def_property_struct_type(prop, "MeshVertex"); RNA_def_property_ui_text(prop, "Vertices", "Vertices of the mesh."); - // XXX RNA_def_property_collection_funcs(prop, "rna_Mesh_verts_begin", 0, 0, 0, 0, 0, 0, "add_verts", "remove_verts"); prop= RNA_def_property(srna, "edges", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "medge", "totedge"); @@ -1121,33 +1237,45 @@ static void rna_def_mesh(BlenderRNA *brna) RNA_def_property_struct_type(prop, "MeshSticky"); RNA_def_property_ui_text(prop, "Sticky", "Sticky texture coordinates."); - /* UV layers */ + /* UV textures */ - prop= RNA_def_property(srna, "uv_layers", PROP_COLLECTION, PROP_NONE); + prop= RNA_def_property(srna, "uv_textures", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "fdata.layers", "fdata.totlayer"); - RNA_def_property_collection_funcs(prop, "rna_Mesh_uv_layers_begin", 0, 0, 0, "rna_Mesh_uv_layers_length", 0, 0, 0, 0); + RNA_def_property_collection_funcs(prop, "rna_Mesh_uv_textures_begin", 0, 0, 0, "rna_Mesh_uv_textures_length", 0, 0, 0, 0); RNA_def_property_struct_type(prop, "MeshTextureFaceLayer"); - RNA_def_property_ui_text(prop, "UV Layers", ""); + RNA_def_property_ui_text(prop, "UV Textures", ""); - prop= RNA_def_property(srna, "active_uv_layer", PROP_POINTER, PROP_UNSIGNED); + prop= RNA_def_property(srna, "active_uv_texture", PROP_POINTER, PROP_UNSIGNED); RNA_def_property_struct_type(prop, "MeshTextureFaceLayer"); - RNA_def_property_pointer_funcs(prop, "rna_Mesh_active_uv_layer_get", "rna_Mesh_active_uv_layer_set", NULL); + RNA_def_property_pointer_funcs(prop, "rna_Mesh_active_uv_texture_get", "rna_Mesh_active_uv_texture_set", NULL); RNA_def_property_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Active UV Layer", "Active UV layer."); + RNA_def_property_ui_text(prop, "Active UV Texture", "Active UV texture."); + RNA_def_property_update(prop, 0, "rna_Mesh_update_data"); - /* VCol layers */ + prop= RNA_def_property(srna, "active_uv_texture_index", PROP_INT, PROP_UNSIGNED); + RNA_def_property_int_funcs(prop, "rna_Mesh_active_uv_texture_index_get", "rna_Mesh_active_uv_texture_index_set", "rna_Mesh_active_uv_texture_index_range"); + RNA_def_property_ui_text(prop, "Active UV Texture Index", "Active UV texture index."); + RNA_def_property_update(prop, 0, "rna_Mesh_update_data"); - prop= RNA_def_property(srna, "vcol_layers", PROP_COLLECTION, PROP_NONE); + /* Vertex colors */ + + prop= RNA_def_property(srna, "vertex_colors", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "fdata.layers", "fdata.totlayer"); - RNA_def_property_collection_funcs(prop, "rna_Mesh_vcol_layers_begin", 0, 0, 0, "rna_Mesh_vcol_layers_length", 0, 0, 0, 0); + RNA_def_property_collection_funcs(prop, "rna_Mesh_vertex_colors_begin", 0, 0, 0, "rna_Mesh_vertex_colors_length", 0, 0, 0, 0); RNA_def_property_struct_type(prop, "MeshColorLayer"); - RNA_def_property_ui_text(prop, "Vertex Color Layers", ""); + RNA_def_property_ui_text(prop, "Vertex Colors", ""); - prop= RNA_def_property(srna, "active_vcol_layer", PROP_POINTER, PROP_UNSIGNED); + prop= RNA_def_property(srna, "active_vertex_color", PROP_POINTER, PROP_UNSIGNED); RNA_def_property_struct_type(prop, "MeshColorLayer"); - RNA_def_property_pointer_funcs(prop, "rna_Mesh_active_vcol_layer_get", "rna_Mesh_active_vcol_layer_set", NULL); + RNA_def_property_pointer_funcs(prop, "rna_Mesh_active_vertex_color_get", "rna_Mesh_active_vertex_color_set", NULL); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Active Vertex Color Layer", "Active vertex color layer."); + RNA_def_property_update(prop, 0, "rna_Mesh_update_data"); + + prop= RNA_def_property(srna, "active_vertex_color_index", PROP_INT, PROP_UNSIGNED); + RNA_def_property_int_funcs(prop, "rna_Mesh_active_vertex_color_index_get", "rna_Mesh_active_vertex_color_index_set", "rna_Mesh_active_vertex_color_index_range"); + RNA_def_property_ui_text(prop, "Active Vertex Color Index", "Active vertex color index."); + RNA_def_property_update(prop, 0, "rna_Mesh_update_data"); prop= RNA_def_property(srna, "float_layers", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "fdata.layers", "fdata.totlayer"); @@ -1183,6 +1311,7 @@ static void rna_def_mesh(BlenderRNA *brna) prop= RNA_def_property(srna, "double_sided", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_TWOSIDED); RNA_def_property_ui_text(prop, "Double Sided", "Render/display the mesh with double or single sided lighting"); + RNA_def_property_update(prop, 0, "rna_Mesh_update_data"); prop= RNA_def_property(srna, "texco_mesh", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "texcomesh"); diff --git a/source/blender/makesrna/intern/rna_mesh_api.c b/source/blender/makesrna/intern/rna_mesh_api.c index 26fb77777d7..c98b3fb7b09 100644 --- a/source/blender/makesrna/intern/rna_mesh_api.c +++ b/source/blender/makesrna/intern/rna_mesh_api.c @@ -34,74 +34,207 @@ #ifdef RNA_RUNTIME -#include "BKE_customdata.h" -#include "BKE_DerivedMesh.h" - #include "DNA_mesh_types.h" #include "DNA_scene_types.h" -/* -void rna_Mesh_copy(Mesh *me, Mesh *from) +#include "BKE_customdata.h" +#include "BKE_depsgraph.h" +#include "BKE_DerivedMesh.h" +#include "BKE_main.h" +#include "BKE_mesh.h" + +#include "BLI_edgehash.h" + +#include "WM_api.h" +#include "WM_types.h" + +static void rna_Mesh_calc_edges(Mesh *mesh) { - copy_mesh_data(me, from); + CustomData edata; + EdgeHashIterator *ehi; + MFace *mf = mesh->mface; + MEdge *med; + EdgeHash *eh = BLI_edgehash_new(); + int i, *index, totedge, totface = mesh->totface; + + for (i = 0; i < totface; i++, mf++) { + if (!BLI_edgehash_haskey(eh, mf->v1, mf->v2)) + BLI_edgehash_insert(eh, mf->v1, mf->v2, NULL); + if (!BLI_edgehash_haskey(eh, mf->v2, mf->v3)) + BLI_edgehash_insert(eh, mf->v2, mf->v3, NULL); + + if (mf->v4) { + if (!BLI_edgehash_haskey(eh, mf->v3, mf->v4)) + BLI_edgehash_insert(eh, mf->v3, mf->v4, NULL); + if (!BLI_edgehash_haskey(eh, mf->v4, mf->v1)) + BLI_edgehash_insert(eh, mf->v4, mf->v1, NULL); + } else { + if (!BLI_edgehash_haskey(eh, mf->v3, mf->v1)) + BLI_edgehash_insert(eh, mf->v3, mf->v1, NULL); + } + } + + totedge = BLI_edgehash_size(eh); + + /* write new edges into a temporary CustomData */ + memset(&edata, 0, sizeof(edata)); + CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge); + + ehi = BLI_edgehashIterator_new(eh); + med = CustomData_get_layer(&edata, CD_MEDGE); + for(i = 0; !BLI_edgehashIterator_isDone(ehi); + BLI_edgehashIterator_step(ehi), ++i, ++med, ++index) { + BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2); + + med->flag = ME_EDGEDRAW|ME_EDGERENDER; + } + BLI_edgehashIterator_free(ehi); + + /* free old CustomData and assign new one */ + CustomData_free(&mesh->edata, mesh->totedge); + mesh->edata = edata; + mesh->totedge = totedge; + + mesh->medge = CustomData_get_layer(&mesh->edata, CD_MEDGE); + + BLI_edgehash_free(eh, NULL); } -void rna_Mesh_copy_applied(Mesh *me, Scene *sce, Object *ob) +static void rna_Mesh_update(Mesh *mesh, bContext *C) { - DerivedMesh *dm= mesh_create_derived_view(sce, ob, CD_MASK_MESH); - DM_to_mesh(dm, me); - dm->release(dm); -} -*/ + Main *bmain= CTX_data_main(C); + Object *ob; -void rna_Mesh_transform(Mesh *me, float **mat) -{ + if(mesh->totface && mesh->totedge == 0) + rna_Mesh_calc_edges(mesh); + + mesh_calc_normals(mesh->mvert, mesh->totvert, mesh->mface, mesh->totface, NULL); + + for(ob=bmain->object.first; ob; ob=ob->id.next) { + if(ob->data == mesh) { + ob->recalc |= OB_RECALC_DATA; + WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob); + } + } } -#if 0 -/* extern struct EditVert *addvertlist(EditMesh *em, float *vec, struct EditVert *example); */ - -static void rna_Mesh_verts_add(PointerRNA *ptr, PointerRNA *ptr_item) +static void rna_Mesh_add_verts(Mesh *mesh, int len) { - //Mesh *me= (Mesh*)ptr->data; + CustomData vdata; + MVert *mvert; + int i, totvert; - /* - // XXX if item is not MVert we fail silently - if (item->type == RNA_MeshVertex) + if(len == 0) return; - // XXX this must be slow... - EditMesh *em= BKE_mesh_get_editmesh(me); + totvert= mesh->totvert + len; + CustomData_copy(&mesh->vdata, &vdata, CD_MASK_MESH, CD_DEFAULT, totvert); + CustomData_copy_data(&mesh->vdata, &vdata, 0, 0, mesh->totvert); - MVert *v = (MVert*)ptr_item->ptr->data; - addvertlist(em, v->co, NULL); + if(!CustomData_has_layer(&vdata, CD_MVERT)) + CustomData_add_layer(&vdata, CD_MVERT, CD_CALLOC, NULL, totvert); - BKE_mesh_end_editmesh(me, em); - */ + CustomData_free(&mesh->vdata, mesh->totvert); + mesh->vdata= vdata; + mesh_update_customdata_pointers(mesh); + + /* scan the input list and insert the new vertices */ + + mvert= &mesh->mvert[mesh->totvert]; + for(i=0; iflag |= SELECT; + + /* set final vertex list size */ + mesh->totvert= totvert; +} + +static void rna_Mesh_add_edges(Mesh *mesh, int len) +{ + CustomData edata; + MEdge *medge; + int i, totedge; + + if(len == 0) + return; + + totedge= mesh->totedge+len; + + /* update customdata */ + CustomData_copy(&mesh->edata, &edata, CD_MASK_MESH, CD_DEFAULT, totedge); + CustomData_copy_data(&mesh->edata, &edata, 0, 0, mesh->totedge); + + if(!CustomData_has_layer(&edata, CD_MEDGE)) + CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge); + + CustomData_free(&mesh->edata, mesh->totedge); + mesh->edata= edata; + mesh_update_customdata_pointers(mesh); + + /* set default flags */ + medge= &mesh->medge[mesh->totedge]; + for(i=0; iflag= ME_EDGEDRAW|ME_EDGERENDER|SELECT; + + mesh->totedge= totedge; +} + +static void rna_Mesh_add_faces(Mesh *mesh, int len) +{ + CustomData fdata; + MFace *mface; + int i, totface; + + if(len == 0) + return; + + totface= mesh->totface + len; /* new face count */ + + /* update customdata */ + CustomData_copy(&mesh->fdata, &fdata, CD_MASK_MESH, CD_DEFAULT, totface); + CustomData_copy_data(&mesh->fdata, &fdata, 0, 0, mesh->totface); + + if(!CustomData_has_layer(&fdata, CD_MFACE)) + CustomData_add_layer(&fdata, CD_MFACE, CD_CALLOC, NULL, totface); + + CustomData_free(&mesh->fdata, mesh->totface); + mesh->fdata= fdata; + mesh_update_customdata_pointers(mesh); + + /* set default flags */ + mface= &mesh->mface[mesh->totface]; + for(i=0; iflag= SELECT; + + mesh->totface= totface; +} + +static void rna_Mesh_add_geometry(Mesh *mesh, int verts, int edges, int faces) +{ + if(verts) + rna_Mesh_add_verts(mesh, verts); + if(edges) + rna_Mesh_add_edges(mesh, edges); + if(faces) + rna_Mesh_add_faces(mesh, faces); } -#endif #else void RNA_api_mesh(StructRNA *srna) { - /*FunctionRNA *func; - PropertyRNA *prop;*/ + FunctionRNA *func; + PropertyRNA *parm; - /* - func= RNA_def_function(srna, "copy", "rna_Mesh_copy"); - RNA_def_function_ui_description(func, "Copy mesh data."); - prop= RNA_def_pointer(func, "src", "Mesh", "", "A mesh to copy data from."); - RNA_def_property_flag(prop, 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); + parm= RNA_def_int(func, "edges", 0, 0, INT_MAX, "Number", "Number of edges to add.", 0, INT_MAX); + RNA_def_property_flag(parm, PROP_REQUIRED); + 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, "add_geom", "rna_Mesh_add_geom"); - RNA_def_function_ui_description(func, "Add geometry data to mesh."); - prop= RNA_def_collection(func, "verts", "?", "", "Vertices."); - RNA_def_property_flag(prop, PROP_REQUIRED); - prop= RNA_def_collection(func, "faces", "?", "", "Faces."); - RNA_def_property_flag(prop, PROP_REQUIRED); - */ + func= RNA_def_function(srna, "update", "rna_Mesh_update"); + RNA_def_function_flag(func, FUNC_USE_CONTEXT); } #endif diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index 3b54409ffb0..2be0d115dc9 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -42,10 +42,13 @@ #ifdef RNA_RUNTIME +#include "DNA_key_types.h" + #include "BKE_armature.h" #include "BKE_context.h" #include "BKE_curve.h" #include "BKE_depsgraph.h" +#include "BKE_key.h" #include "BKE_material.h" #include "BKE_mesh.h" #include "BKE_particle.h" @@ -131,6 +134,27 @@ static PointerRNA rna_Object_active_vertex_group_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_VertexGroup, BLI_findlink(&ob->defbase, ob->actdef)); } +static int rna_Object_active_vertex_group_index_get(PointerRNA *ptr) +{ + Object *ob= (Object*)ptr->id.data; + return MAX2(ob->actdef-1, 0); +} + +static void rna_Object_active_vertex_group_index_set(PointerRNA *ptr, int value) +{ + Object *ob= (Object*)ptr->id.data; + ob->actdef= value+1; +} + +static void rna_Object_active_vertex_group_index_range(PointerRNA *ptr, int *min, int *max) +{ + Object *ob= (Object*)ptr->id.data; + + *min= 0; + *max= BLI_countlist(&ob->defbase)-1; + *max= MAX2(0, *max); +} + void rna_object_vgroup_name_index_get(PointerRNA *ptr, char *value, int index) { Object *ob= (Object*)ptr->id.data; @@ -228,11 +252,23 @@ void rna_object_vcollayer_name_set(PointerRNA *ptr, const char *value, char *res BLI_strncpy(result, "", maxlen); } +static int rna_Object_active_material_index_get(PointerRNA *ptr) +{ + Object *ob= (Object*)ptr->id.data; + return MAX2(ob->actcol-1, 0); +} + +static void rna_Object_active_material_index_set(PointerRNA *ptr, int value) +{ + Object *ob= (Object*)ptr->id.data; + ob->actcol= value+1; +} + static void rna_Object_active_material_index_range(PointerRNA *ptr, int *min, int *max) { Object *ob= (Object*)ptr->id.data; - *min= 1; - *max= ob->totcol; + *min= 0; + *max= MAX2(ob->totcol-1, 0); } static PointerRNA rna_Object_active_material_get(PointerRNA *ptr) @@ -244,14 +280,15 @@ static PointerRNA rna_Object_active_material_get(PointerRNA *ptr) static void rna_Object_active_particle_system_index_range(PointerRNA *ptr, int *min, int *max) { Object *ob= (Object*)ptr->id.data; - *min= 1; - *max= BLI_countlist(&ob->particlesystem); + *min= 0; + *max= BLI_countlist(&ob->particlesystem)-1; + *max= MAX2(0, *max); } static int rna_Object_active_particle_system_index_get(PointerRNA *ptr) { Object *ob= (Object*)ptr->id.data; - return psys_get_current_num(ob) + 1; + return psys_get_current_num(ob); } static void rna_Object_active_particle_system_index_set(struct PointerRNA *ptr, int value) @@ -384,6 +421,41 @@ static void rna_GameObjectSettings_state_set(PointerRNA *ptr, const int *values) } } +static void rna_Object_active_shape_key_index_range(PointerRNA *ptr, int *min, int *max) +{ + Object *ob= (Object*)ptr->id.data; + Key *key= ob_get_key(ob); + + *min= 0; + *max= (key)? BLI_countlist(&key->block)-1: 0; + *max= MAX2(0, *max); +} + +static int rna_Object_active_shape_key_index_get(PointerRNA *ptr) +{ + Object *ob= (Object*)ptr->id.data; + + return MAX2(ob->shapenr-1, 0); +} + +static void rna_Object_active_shape_key_index_set(PointerRNA *ptr, int value) +{ + Object *ob= (Object*)ptr->id.data; + + ob->shapenr= value+1; + ob->shapeflag |= OB_SHAPE_TEMPLOCK; +} + +static void rna_Object_shape_key_lock_set(PointerRNA *ptr, int value) +{ + Object *ob= (Object*)ptr->id.data; + + if(value) ob->shapeflag |= OB_SHAPE_LOCK; + else ob->shapeflag &= ~OB_SHAPE_LOCK; + + ob->shapeflag &= ~OB_SHAPE_TEMPLOCK; +} + #else static void rna_def_vertex_group(BlenderRNA *brna) @@ -814,7 +886,7 @@ static void rna_def_object(BlenderRNA *brna) prop= RNA_def_property(srna, "active_material_index", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "actcol"); - RNA_def_property_int_funcs(prop, NULL, NULL, "rna_Object_active_material_index_range"); + RNA_def_property_int_funcs(prop, "rna_Object_active_material_index_get", "rna_Object_active_material_index_set", "rna_Object_active_material_index_range"); RNA_def_property_ui_text(prop, "Active Material Index", "Index of active material slot."); /* transform */ @@ -895,8 +967,15 @@ static void rna_def_object(BlenderRNA *brna) prop= RNA_def_property(srna, "active_vertex_group", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "VertexGroup"); - RNA_def_property_pointer_funcs(prop, "rna_Object_active_vertex_group_get", NULL, NULL); + RNA_def_property_pointer_funcs(prop, "rna_Object_active_vertex_group_get", "rna_Object_active_vertex_group_set", NULL); RNA_def_property_ui_text(prop, "Active Vertex Group", "Vertex groups of the object."); + RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_Object_update_data"); + + prop= RNA_def_property(srna, "active_vertex_group_index", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "actdef"); + RNA_def_property_int_funcs(prop, "rna_Object_active_vertex_group_index_get", "rna_Object_active_vertex_group_index_set", "rna_Object_active_vertex_group_index_range"); + RNA_def_property_ui_text(prop, "Active Vertex Group Index", "Active index in vertex group array."); + RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_Object_update_data"); /* empty */ @@ -1148,13 +1227,15 @@ static void rna_def_object(BlenderRNA *brna) 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_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_boolean_funcs(prop, NULL, "rna_Object_shape_key_lock_set"); RNA_def_property_ui_text(prop, "Shape Key Lock", "Always show the current Shape for this Object."); + RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_Object_update_data"); - prop= RNA_def_property(srna, "active_shape_key", PROP_INT, PROP_NONE); + prop= RNA_def_property(srna, "active_shape_key_index", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "shapenr"); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Active Shape Key", "Current shape key index."); + RNA_def_property_int_funcs(prop, "rna_Object_active_shape_key_index_get", "rna_Object_active_shape_key_index_set", "rna_Object_active_shape_key_index_range"); + RNA_def_property_ui_text(prop, "Active Shape Key Index", "Current shape key index."); + RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_Object_update_data"); RNA_api_object(srna); } diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c index 6fa275cec91..14db8ea3377 100644 --- a/source/blender/makesrna/intern/rna_rna.c +++ b/source/blender/makesrna/intern/rna_rna.c @@ -309,14 +309,16 @@ PointerRNA rna_builtin_properties_lookup_string(PointerRNA *ptr, const char *key } } while((srna=srna->base)); - group= RNA_struct_idproperties(ptr, 0); + if(ptr->data) { + group= RNA_struct_idproperties(ptr, 0); - if(group) { - for(idp=group->data.group.first; idp; idp=idp->next) { - if(strcmp(idp->name, key) == 0) { - propptr.type= &RNA_Property; - propptr.data= idp; - return propptr; + if(group) { + for(idp=group->data.group.first; idp; idp=idp->next) { + if(strcmp(idp->name, key) == 0) { + propptr.type= &RNA_Property; + propptr.data= idp; + return propptr; + } } } } diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 47c9025149a..5f03b7167f4 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -245,6 +245,11 @@ 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); + RNA_def_property_float_sdna(prop, NULL, "vgroup_weight"); + RNA_def_property_ui_text(prop, "Vertex Group Weight", "Weight to assign in vertex groups."); + + /* Sculpt */ rna_def_sculpt(brna); } diff --git a/source/blender/makesrna/intern/rna_screen.c b/source/blender/makesrna/intern/rna_screen.c index b7279757455..a4ba6ec172b 100644 --- a/source/blender/makesrna/intern/rna_screen.c +++ b/source/blender/makesrna/intern/rna_screen.c @@ -42,6 +42,31 @@ EnumPropertyItem region_type_items[] = { #ifdef RNA_RUNTIME +#include "WM_api.h" +#include "WM_types.h" + +static void rna_Screen_scene_set(PointerRNA *ptr, PointerRNA value) +{ + bScreen *sc= (bScreen*)ptr->data; + + if(value.data == NULL) + return; + + /* exception: can't set screens inside of area/region handers */ + sc->newscene= value.data; +} + +static void rna_Screen_scene_update(bContext *C, PointerRNA *ptr) +{ + bScreen *sc= (bScreen*)ptr->data; + + /* exception: can't set screens inside of area/region handers */ + if(sc->newscene) { + WM_event_add_notifier(C, NC_SCENE|ND_SCENEBROWSE, sc->newscene); + sc->newscene= NULL; + } +} + #else static void rna_def_scrarea(BlenderRNA *brna) @@ -94,6 +119,9 @@ static void rna_def_bscreen(BlenderRNA *brna) 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); + RNA_def_property_pointer_funcs(prop, NULL, "rna_Screen_scene_set", NULL); + RNA_def_property_update(prop, 0, "rna_Screen_scene_update"); prop= RNA_def_property(srna, "areas", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "areabase", NULL); diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 9335b3619fc..b29186513f8 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -96,8 +96,8 @@ static StructRNA* rna_Space_refine(struct PointerRNA *ptr) return &RNA_SpaceOutliner; case SPACE_BUTS: return &RNA_SpaceButtonsWindow; - /* case SPACE_FILE: - return &RNA_SpaceFileBrowser;*/ + case SPACE_FILE: + return &RNA_SpaceFileBrowser; case SPACE_IMAGE: return &RNA_SpaceImageEditor; /*case SPACE_INFO: @@ -210,6 +210,13 @@ 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 Buttons */ StructRNA *rna_SpaceButtonsWindow_pin_id_typef(PointerRNA *ptr) @@ -971,12 +978,124 @@ static void rna_def_space_nla(BlenderRNA *brna) // TODO... autosnap, dopesheet? } +static void rna_def_fileselect_params(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + static EnumPropertyItem file_display_items[] = { + {FILE_SHORTDISPLAY, "FILE_SHORTDISPLAY", ICON_SHORTDISPLAY, "Short List", "Display files as short list"}, + {FILE_LONGDISPLAY, "FILE_LONGDISPLAY", ICON_LONGDISPLAY, "Long List", "Display files as a detailed list"}, + {FILE_IMGDISPLAY, "FILE_IMGDISPLAY", ICON_IMGDISPLAY, "Thumbnails", "Display files as thumbnails"}, + {0, NULL, 0, NULL, NULL}}; + + static EnumPropertyItem file_sort_items[] = { + {FILE_SORT_ALPHA, "FILE_SORT_ALPHA", ICON_SORTALPHA, "Sort alphabetically", "Sort the file list alphabetically."}, + {FILE_SORT_EXTENSION, "FILE_SORT_EXTENSION", ICON_SORTBYEXT, "Sort by extension", "Sort the file list by extension."}, + {FILE_SORT_TIME, "FILE_SORT_TIME", ICON_SORTTIME, "Sort by time", "Sort files by modification time."}, + {FILE_SORT_SIZE, "FILE_SORT_SIZE", ICON_SORTSIZE, "Sort by size", "Sort files by size."}, + {0, NULL, 0, NULL, NULL}}; + + srna= RNA_def_struct(brna, "FileSelectParams", NULL); + RNA_def_struct_ui_text(srna, "File Select Parameters", "File Select Parameters."); + + prop= RNA_def_property(srna, "display", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "display"); + RNA_def_property_enum_items(prop, file_display_items); + RNA_def_property_ui_text(prop, "Display Mode", "Display mode for the file list"); + RNA_def_property_update(prop, NC_FILE | ND_PARAMS, NULL); + + prop= RNA_def_property(srna, "do_filter", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", FILE_FILTER); + RNA_def_property_ui_text(prop, "Filter Files", "Enable filtering of files."); + RNA_def_property_update(prop, NC_FILE | ND_PARAMS, NULL); + + prop= RNA_def_property(srna, "hide_dot", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", FILE_HIDE_DOT); + RNA_def_property_ui_text(prop, "Hide Dot Files", "Hide hidden dot files."); + RNA_def_property_update(prop, NC_FILE | ND_FILELIST , NULL); + + prop= RNA_def_property(srna, "sort", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "sort"); + RNA_def_property_enum_items(prop, file_sort_items); + RNA_def_property_ui_text(prop, "Sort", ""); + RNA_def_property_update(prop, NC_FILE | ND_PARAMS, NULL); + + prop= RNA_def_property(srna, "filter_image", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "filter", IMAGEFILE); + RNA_def_property_ui_text(prop, "Filter Images", "Show image files."); + RNA_def_property_ui_icon(prop, ICON_FILE_IMAGE, 0); + RNA_def_property_update(prop, NC_FILE | ND_PARAMS, NULL); + + prop= RNA_def_property(srna, "filter_blender", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "filter", BLENDERFILE); + RNA_def_property_ui_text(prop, "Filter Blender", "Show .blend files."); + RNA_def_property_ui_icon(prop, ICON_FILE_BLEND, 0); + RNA_def_property_update(prop, NC_FILE | ND_PARAMS, NULL); + + prop= RNA_def_property(srna, "filter_movie", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "filter", MOVIEFILE); + RNA_def_property_ui_text(prop, "Filter Movies", "Show movie files."); + RNA_def_property_ui_icon(prop, ICON_FILE_MOVIE, 0); + RNA_def_property_update(prop, NC_FILE | ND_PARAMS, NULL); + + prop= RNA_def_property(srna, "filter_script", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "filter", PYSCRIPTFILE); + RNA_def_property_ui_text(prop, "Filter Script", "Show script files."); + RNA_def_property_ui_icon(prop, ICON_FILE_SCRIPT, 0); + RNA_def_property_update(prop, NC_FILE | ND_PARAMS, NULL); + + prop= RNA_def_property(srna, "filter_font", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "filter", FTFONTFILE); + RNA_def_property_ui_text(prop, "Filter Fonts", "Show font files."); + RNA_def_property_ui_icon(prop, ICON_FILE_FONT, 0); + RNA_def_property_update(prop, NC_FILE | ND_PARAMS, NULL); + + prop= RNA_def_property(srna, "filter_sound", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "filter", SOUNDFILE); + RNA_def_property_ui_text(prop, "Filter Sound", "Show sound files."); + RNA_def_property_ui_icon(prop, ICON_FILE_SOUND, 0); + RNA_def_property_update(prop, NC_FILE | ND_PARAMS, NULL); + + prop= RNA_def_property(srna, "filter_text", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "filter", TEXTFILE); + RNA_def_property_ui_text(prop, "Filter Text", "Show text files."); + RNA_def_property_ui_icon(prop, ICON_FILE_BLANK, 0); + RNA_def_property_update(prop, NC_FILE | ND_PARAMS, NULL); + + prop= RNA_def_property(srna, "filter_folder", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "filter", FOLDERFILE); + RNA_def_property_ui_text(prop, "Filter Folder", "Show folders."); + RNA_def_property_ui_icon(prop, ICON_FILE_FOLDER, 0); + RNA_def_property_update(prop, NC_FILE | ND_PARAMS, NULL); + + +} + +static void rna_def_space_filebrowser(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna= RNA_def_struct(brna, "SpaceFileBrowser", "Space"); + RNA_def_struct_sdna(srna, "SpaceFile"); + RNA_def_struct_ui_text(srna, "Space File Browser", "File browser space data."); + + 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."); + +} + void RNA_def_space(BlenderRNA *brna) { rna_def_space(brna); rna_def_space_image(brna); rna_def_space_sequencer(brna); rna_def_space_text(brna); + rna_def_fileselect_params(brna); + rna_def_space_filebrowser(brna); rna_def_space_outliner(brna); rna_def_background_image(brna); rna_def_space_3dview(brna); diff --git a/source/blender/makesrna/intern/rna_ui.c b/source/blender/makesrna/intern/rna_ui.c index 825b3711b97..eef221e45a4 100644 --- a/source/blender/makesrna/intern/rna_ui.c +++ b/source/blender/makesrna/intern/rna_ui.c @@ -416,12 +416,12 @@ static int rna_UILayout_active_get(struct PointerRNA *ptr) static void rna_UILayout_active_set(struct PointerRNA *ptr, int value) { - return uiLayoutSetActive(ptr->data, value); + uiLayoutSetActive(ptr->data, value); } static void rna_UILayout_op_context_set(struct PointerRNA *ptr, int value) { - return uiLayoutSetOperatorContext(ptr->data, value); + uiLayoutSetOperatorContext(ptr->data, value); } static int rna_UILayout_op_context_get(struct PointerRNA *ptr) @@ -436,7 +436,7 @@ static int rna_UILayout_enabled_get(struct PointerRNA *ptr) static void rna_UILayout_enabled_set(struct PointerRNA *ptr, int value) { - return uiLayoutSetEnabled(ptr->data, value); + uiLayoutSetEnabled(ptr->data, value); } static int rna_UILayout_red_alert_get(struct PointerRNA *ptr) @@ -446,7 +446,7 @@ static int rna_UILayout_red_alert_get(struct PointerRNA *ptr) static void rna_UILayout_red_alert_set(struct PointerRNA *ptr, int value) { - return uiLayoutSetRedAlert(ptr->data, value); + uiLayoutSetRedAlert(ptr->data, value); } static int rna_UILayout_keep_aspect_get(struct PointerRNA *ptr) @@ -456,7 +456,7 @@ static int rna_UILayout_keep_aspect_get(struct PointerRNA *ptr) static void rna_UILayout_keep_aspect_set(struct PointerRNA *ptr, int value) { - return uiLayoutSetKeepAspect(ptr->data, value); + uiLayoutSetKeepAspect(ptr->data, value); } static int rna_UILayout_alignment_get(struct PointerRNA *ptr) @@ -466,7 +466,7 @@ static int rna_UILayout_alignment_get(struct PointerRNA *ptr) static void rna_UILayout_alignment_set(struct PointerRNA *ptr, int value) { - return uiLayoutSetAlignment(ptr->data, value); + uiLayoutSetAlignment(ptr->data, value); } static float rna_UILayout_scale_x_get(struct PointerRNA *ptr) @@ -476,7 +476,7 @@ static float rna_UILayout_scale_x_get(struct PointerRNA *ptr) static void rna_UILayout_scale_x_set(struct PointerRNA *ptr, float value) { - return uiLayoutSetScaleX(ptr->data, value); + uiLayoutSetScaleX(ptr->data, value); } static float rna_UILayout_scale_y_get(struct PointerRNA *ptr) @@ -486,7 +486,7 @@ static float rna_UILayout_scale_y_get(struct PointerRNA *ptr) static void rna_UILayout_scale_y_set(struct PointerRNA *ptr, float value) { - return uiLayoutSetScaleY(ptr->data, value); + uiLayoutSetScaleY(ptr->data, value); } #else // RNA_RUNTIME diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c index a4aa60775f2..3df3fad3f15 100644 --- a/source/blender/makesrna/intern/rna_ui_api.c +++ b/source/blender/makesrna/intern/rna_ui_api.c @@ -259,6 +259,8 @@ void RNA_api_ui_layout(StructRNA *srna) func= RNA_def_function(srna, "template_list", "uiTemplateList"); api_ui_item_rna_common(func); + 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); 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); @@ -266,6 +268,11 @@ void RNA_api_ui_layout(StructRNA *srna) parm= RNA_def_boolean(func, "compact", 0, "", "Use compact, single row list template."); parm= RNA_def_collection(func, "items", 0, "", "Items visible in the list."); RNA_def_function_return(func, parm); + + func= RNA_def_function(srna, "template_running_jobs", "uiTemplateRunningJobs"); + RNA_def_function_flag(func, FUNC_USE_CONTEXT); + + func= RNA_def_function(srna, "template_operator_search", "uiTemplateOperatorSearch"); } #endif diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index 1bfc3b6f8f6..f8ab3a86744 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -147,6 +147,8 @@ EnumPropertyItem event_type_items[] = { #ifdef RNA_RUNTIME +#include "WM_api.h" + #include "BKE_idprop.h" static wmOperator *rna_OperatorProperties_find_operator(PointerRNA *ptr) @@ -215,6 +217,28 @@ static int rna_Event_ascii_length(PointerRNA *ptr) return (event->ascii)? 1 : 0; } +static void rna_Window_screen_set(PointerRNA *ptr, PointerRNA value) +{ + wmWindow *win= (wmWindow*)ptr->data; + + if(value.data == NULL) + return; + + /* exception: can't set screens inside of area/region handers */ + win->newscreen= value.data; +} + +static void rna_Window_screen_update(bContext *C, PointerRNA *ptr) +{ + wmWindow *win= (wmWindow*)ptr->data; + + /* exception: can't set screens inside of area/region handers */ + if(win->newscreen) { + WM_event_add_notifier(C, NC_SCREEN|ND_SCREENBROWSE, win->newscreen); + win->newscreen= NULL; + } +} + #else static void rna_def_operator(BlenderRNA *brna) @@ -349,6 +373,23 @@ static void rna_def_event(BlenderRNA *brna) RNA_def_property_ui_text(prop, "OS Key", "True when the shift key is held."); } +static void rna_def_window(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna= RNA_def_struct(brna, "Window", NULL); + 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); + 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); + RNA_def_property_pointer_funcs(prop, NULL, "rna_Window_screen_set", NULL); + RNA_def_property_update(prop, 0, "rna_Window_screen_update"); +} + static void rna_def_windowmanager(BlenderRNA *brna) { StructRNA *srna; @@ -362,6 +403,10 @@ static void rna_def_windowmanager(BlenderRNA *brna) RNA_def_property_struct_type(prop, "Operator"); RNA_def_property_ui_text(prop, "Operators", "Operator registry."); + prop= RNA_def_property(srna, "windows", PROP_COLLECTION, PROP_NONE); + RNA_def_property_struct_type(prop, "Window"); + RNA_def_property_ui_text(prop, "Windows", "Open windows."); + RNA_api_wm(srna); } @@ -371,6 +416,7 @@ void RNA_def_wm(BlenderRNA *brna) rna_def_operator_utils(brna); rna_def_operator_filelist_element(brna); rna_def_event(brna); + rna_def_window(brna); rna_def_windowmanager(brna); } diff --git a/source/blender/python/generic/BGL.c b/source/blender/python/generic/BGL.c index a90fabd3586..de82781cf3a 100644 --- a/source/blender/python/generic/BGL.c +++ b/source/blender/python/generic/BGL.c @@ -83,8 +83,13 @@ static PyObject *Buffer_getattr( PyObject * self, char *name ); static PyObject *Buffer_repr( PyObject * self ); PyTypeObject buffer_Type = { - PyObject_HEAD_INIT( NULL ) /* required python macro */ - 0, /*ob_size */ +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "buffer", /*tp_name */ sizeof( Buffer ), /*tp_basicsize */ 0, /*tp_itemsize */ diff --git a/source/blender/python/generic/Geometry.c b/source/blender/python/generic/Geometry.c index 8a748241570..b4a34d30051 100644 --- a/source/blender/python/generic/Geometry.c +++ b/source/blender/python/generic/Geometry.c @@ -273,7 +273,7 @@ static PyObject *M_Geometry_LineIntersect2D( PyObject * self, PyObject * args ) /*X of vert, Y of hoz. no calculation needed */ newvec[0]= a1x; newvec[1]= b1y; - return newVectorObject(newvec, 2, Py_NEW); + return newVectorObject(newvec, 2, Py_NEW, NULL); } yi = (float)(((b1y / fabs(b1x - b2x)) * fabs(b2x - a1x)) + ((b2y / fabs(b1x - b2x)) * fabs(b1x - a1x))); @@ -285,7 +285,7 @@ static PyObject *M_Geometry_LineIntersect2D( PyObject * self, PyObject * args ) } newvec[0]= a1x; newvec[1]= yi; - return newVectorObject(newvec, 2, Py_NEW); + return newVectorObject(newvec, 2, Py_NEW, NULL); } else if (fabs(a2y-a1y) < eul) { /* hoz line1 */ if (fabs(b2y-b1y) < eul) { /*hoz line2*/ Py_RETURN_NONE; /*2 hoz lines dont intersect*/ @@ -300,7 +300,7 @@ static PyObject *M_Geometry_LineIntersect2D( PyObject * self, PyObject * args ) } newvec[0]= xi; newvec[1]= a1y; - return newVectorObject(newvec, 2, Py_NEW); + return newVectorObject(newvec, 2, Py_NEW, NULL); } b1 = (a2y-a1y)/(a2x-a1x); @@ -317,7 +317,7 @@ static PyObject *M_Geometry_LineIntersect2D( PyObject * self, PyObject * args ) if ((a1x-xi)*(xi-a2x) >= 0 && (b1x-xi)*(xi-b2x) >= 0 && (a1y-yi)*(yi-a2y) >= 0 && (b1y-yi)*(yi-b2y)>=0) { newvec[0]= xi; newvec[1]= yi; - return newVectorObject(newvec, 2, Py_NEW); + return newVectorObject(newvec, 2, Py_NEW, NULL); } Py_RETURN_NONE; } @@ -355,7 +355,7 @@ static PyObject *M_Geometry_ClosestPointOnLine( PyObject * self, PyObject * args lambda = lambda_cp_line_ex(pt_in, l1, l2, pt_out); ret = PyTuple_New(2); - PyTuple_SET_ITEM( ret, 0, newVectorObject(pt_out, 3, Py_NEW) ); + PyTuple_SET_ITEM( ret, 0, newVectorObject(pt_out, 3, Py_NEW, NULL) ); PyTuple_SET_ITEM( ret, 1, PyFloat_FromDouble(lambda) ); return ret; } @@ -535,7 +535,7 @@ static PyObject *M_Geometry_BezierInterp( PyObject * self, PyObject * args ) list= PyList_New(resolu); fp= coord_array; for(i=0; iquat[3]*quat->quat[3]*vec->vec[2] - 2*quat->quat[0]*quat->quat[2]*vec->vec[0] - quat->quat[2]*quat->quat[2]*vec->vec[2] + 2*quat->quat[0]*quat->quat[1]*vec->vec[1] - quat->quat[1]*quat->quat[1]*vec->vec[2] + quat->quat[0]*quat->quat[0]*vec->vec[2]; - return newVectorObject(rot, 3, Py_NEW); + return newVectorObject(rot, 3, Py_NEW, NULL); } }else if(VectorObject_Check(arg1)){ vec = (VectorObject*)arg1; @@ -201,7 +201,7 @@ PyObject *quat_rotation(PyObject *arg1, PyObject *arg2) quat->quat[3]*quat->quat[3]*vec->vec[2] - 2*quat->quat[0]*quat->quat[2]*vec->vec[0] - quat->quat[2]*quat->quat[2]*vec->vec[2] + 2*quat->quat[0]*quat->quat[1]*vec->vec[1] - quat->quat[1]*quat->quat[1]*vec->vec[2] + quat->quat[0]*quat->quat[0]*vec->vec[2]; - return newVectorObject(rot, 3, Py_NEW); + return newVectorObject(rot, 3, Py_NEW, NULL); } } @@ -311,7 +311,7 @@ static PyObject *M_Mathutils_MidpointVecs(PyObject * self, PyObject * args) for(x = 0; x < vec1->size; x++) { vec[x] = 0.5f * (vec1->vec[x] + vec2->vec[x]); } - return newVectorObject(vec, vec1->size, Py_NEW); + return newVectorObject(vec, vec1->size, Py_NEW, NULL); } //----------------------------------Mathutils.ProjectVecs() ------------- //projects vector 1 onto vector 2 @@ -348,7 +348,7 @@ static PyObject *M_Mathutils_ProjectVecs(PyObject * self, PyObject * args) for(x = 0; x < size; x++) { vec[x] = (float)(dot * vec2->vec[x]); } - return newVectorObject(vec, size, Py_NEW); + return newVectorObject(vec, size, Py_NEW, NULL); } //----------------------------------MATRIX FUNCTIONS-------------------- //----------------------------------Mathutils.RotationMatrix() ---------- @@ -493,7 +493,7 @@ static PyObject *M_Mathutils_RotationMatrix(PyObject * self, PyObject * args) mat[3] = 0.0f; } //pass to matrix creation - return newMatrixObject(mat, matSize, matSize, Py_NEW); + return newMatrixObject(mat, matSize, matSize, Py_NEW, NULL); } //----------------------------------Mathutils.TranslationMatrix() ------- //creates a translation matrix @@ -520,7 +520,7 @@ static PyObject *M_Mathutils_TranslationMatrix(PyObject * self, VectorObject * v mat[13] = vec->vec[1]; mat[14] = vec->vec[2]; - return newMatrixObject(mat, 4, 4, Py_NEW); + return newMatrixObject(mat, 4, 4, Py_NEW, NULL); } //----------------------------------Mathutils.ScaleMatrix() ------------- //mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc. @@ -598,7 +598,7 @@ static PyObject *M_Mathutils_ScaleMatrix(PyObject * self, PyObject * args) mat[3] = 0.0f; } //pass to matrix creation - return newMatrixObject(mat, matSize, matSize, Py_NEW); + return newMatrixObject(mat, matSize, matSize, Py_NEW, NULL); } //----------------------------------Mathutils.OrthoProjectionMatrix() --- //mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc. @@ -701,7 +701,7 @@ static PyObject *M_Mathutils_OrthoProjectionMatrix(PyObject * self, PyObject * a mat[3] = 0.0f; } //pass to matrix creation - return newMatrixObject(mat, matSize, matSize, Py_NEW); + return newMatrixObject(mat, matSize, matSize, Py_NEW, NULL); } //----------------------------------Mathutils.ShearMatrix() ------------- //creates a shear matrix @@ -768,7 +768,7 @@ static PyObject *M_Mathutils_ShearMatrix(PyObject * self, PyObject * args) mat[3] = 0.0f; } //pass to matrix creation - return newMatrixObject(mat, matSize, matSize, Py_NEW); + return newMatrixObject(mat, matSize, matSize, Py_NEW, NULL); } //----------------------------------QUATERNION FUNCTIONS----------------- @@ -801,7 +801,7 @@ static PyObject *M_Mathutils_DifferenceQuats(PyObject * self, PyObject * args) tempQuat[x] /= (float)(dot * dot); } QuatMul(quat, tempQuat, quatV->quat); - return newQuaternionObject(quat, Py_NEW); + return newQuaternionObject(quat, Py_NEW, NULL); } //----------------------------------Mathutils.Slerp() ------------------ //attemps to interpolate 2 quaternions and return the result @@ -862,7 +862,7 @@ static PyObject *M_Mathutils_Slerp(PyObject * self, PyObject * args) quat[2] = (float)(quat_u[2] * x + quat_v[2] * y); quat[3] = (float)(quat_u[3] * x + quat_v[3] * y); - return newQuaternionObject(quat, Py_NEW); + return newQuaternionObject(quat, Py_NEW, NULL); } //----------------------------------EULER FUNCTIONS---------------------- //---------------------------------INTERSECTION FUNCTIONS-------------------- @@ -936,7 +936,7 @@ static PyObject *M_Mathutils_Intersect( PyObject * self, PyObject * args ) VecMulf(dir, t); VecAddf(pvec, orig, dir); - return newVectorObject(pvec, 3, Py_NEW); + return newVectorObject(pvec, 3, Py_NEW, NULL); } //----------------------------------Mathutils.LineIntersect() ------------------- /* Line-Line intersection using algorithm from mathworld.wolfram.com */ @@ -993,8 +993,8 @@ static PyObject *M_Mathutils_LineIntersect( PyObject * self, PyObject * args ) } else { tuple = PyTuple_New( 2 ); - PyTuple_SetItem( tuple, 0, newVectorObject(i1, vec1->size, Py_NEW) ); - PyTuple_SetItem( tuple, 1, newVectorObject(i2, vec1->size, Py_NEW) ); + PyTuple_SetItem( tuple, 0, newVectorObject(i1, vec1->size, Py_NEW, NULL) ); + PyTuple_SetItem( tuple, 1, newVectorObject(i2, vec1->size, Py_NEW, NULL) ); return tuple; } } @@ -1055,7 +1055,7 @@ static PyObject *M_Mathutils_QuadNormal( PyObject * self, PyObject * args ) VecAddf(n1, n2, n1); Normalize(n1); - return newVectorObject(n1, 3, Py_NEW); + return newVectorObject(n1, 3, Py_NEW, NULL); } //----------------------------Mathutils.TriangleNormal() ------------------- @@ -1091,7 +1091,7 @@ static PyObject *M_Mathutils_TriangleNormal( PyObject * self, PyObject * args ) Crossf(n, e2, e1); Normalize(n); - return newVectorObject(n, 3, Py_NEW); + return newVectorObject(n, 3, Py_NEW, NULL); } //--------------------------------- AREA FUNCTIONS-------------------- @@ -1244,7 +1244,7 @@ PyObject *BaseMathObject_getOwner( BaseMathObject * self, void *type ) PyObject *BaseMathObject_getWrapped( BaseMathObject *self, void *type ) { - PyBool_FromLong((self->wrapped == Py_WRAP) ? 1:0); + return PyBool_FromLong((self->wrapped == Py_WRAP) ? 1:0); } void BaseMathObject_dealloc(BaseMathObject * self) @@ -1254,6 +1254,6 @@ void BaseMathObject_dealloc(BaseMathObject * self) PyMem_Free(self->data); Py_XDECREF(self->cb_user); - PyObject_DEL(self); + Py_TYPE(self)->tp_free(self); // PyObject_DEL(self); // breaks subtypes } diff --git a/source/blender/python/generic/euler.c b/source/blender/python/generic/euler.c index 9041eb84a3d..1e0632f4040 100644 --- a/source/blender/python/generic/euler.c +++ b/source/blender/python/generic/euler.c @@ -34,13 +34,6 @@ //-------------------------DOC STRINGS --------------------------- -static char Euler_Zero_doc[] = "() - set all values in the euler to 0"; -static char Euler_Unique_doc[] ="() - sets the euler rotation a unique shortest arc rotation - tests for gimbal lock"; -static char Euler_ToMatrix_doc[] = "() - returns a rotation matrix representing the euler rotation"; -static char Euler_ToQuat_doc[] = "() - returns a quaternion representing the euler rotation"; -static char Euler_Rotate_doc[] = "() - rotate a euler by certain amount around an axis of rotation"; -static char Euler_copy_doc[] = "() - returns a copy of the euler."; -static char Euler_MakeCompatible_doc[] = "(euler) - Make this user compatible with another (no axis flipping)."; static PyObject *Euler_Zero( EulerObject * self ); static PyObject *Euler_Unique( EulerObject * self ); @@ -52,22 +45,21 @@ static PyObject *Euler_copy( EulerObject * self, PyObject *args ); //-----------------------METHOD DEFINITIONS ---------------------- static struct PyMethodDef Euler_methods[] = { - {"zero", (PyCFunction) Euler_Zero, METH_NOARGS, Euler_Zero_doc}, - {"unique", (PyCFunction) Euler_Unique, METH_NOARGS, Euler_Unique_doc}, - {"toMatrix", (PyCFunction) Euler_ToMatrix, METH_NOARGS, Euler_ToMatrix_doc}, - {"toQuat", (PyCFunction) Euler_ToQuat, METH_NOARGS, Euler_ToQuat_doc}, - {"rotate", (PyCFunction) Euler_Rotate, METH_VARARGS, Euler_Rotate_doc}, - {"makeCompatible", (PyCFunction) Euler_MakeCompatible, METH_O, Euler_MakeCompatible_doc}, - {"__copy__", (PyCFunction) Euler_copy, METH_VARARGS, Euler_copy_doc}, - {"copy", (PyCFunction) Euler_copy, METH_VARARGS, Euler_copy_doc}, + {"zero", (PyCFunction) Euler_Zero, METH_NOARGS, NULL}, + {"unique", (PyCFunction) Euler_Unique, METH_NOARGS, NULL}, + {"toMatrix", (PyCFunction) Euler_ToMatrix, METH_NOARGS, NULL}, + {"toQuat", (PyCFunction) Euler_ToQuat, METH_NOARGS, NULL}, + {"rotate", (PyCFunction) Euler_Rotate, METH_VARARGS, NULL}, + {"makeCompatible", (PyCFunction) Euler_MakeCompatible, METH_O, NULL}, + {"__copy__", (PyCFunction) Euler_copy, METH_VARARGS, NULL}, + {"copy", (PyCFunction) Euler_copy, METH_VARARGS, NULL}, {NULL, NULL, 0, NULL} }; //----------------------------------Mathutils.Euler() ------------------- //makes a new euler for you to play with -static PyObject *Euler_new(PyObject * self, PyObject * args) +static PyObject *Euler_new(PyTypeObject * type, PyObject * args, PyObject * kwargs) { - PyObject *listObject = NULL; int size, i; float eul[3]; @@ -84,7 +76,7 @@ static PyObject *Euler_new(PyObject * self, PyObject * args) } } else if (size == 0) { //returns a new empty 3d euler - return newEulerObject(NULL, Py_NEW); + return newEulerObject(NULL, Py_NEW, NULL); } else { listObject = args; } @@ -110,7 +102,7 @@ static PyObject *Euler_new(PyObject * self, PyObject * args) return NULL; } } - return newEulerObject(eul, Py_NEW); + return newEulerObject(eul, Py_NEW, NULL); } //-----------------------------METHODS---------------------------- @@ -118,8 +110,11 @@ static PyObject *Euler_new(PyObject * self, PyObject * args) //return a quaternion representation of the euler static PyObject *Euler_ToQuat(EulerObject * self) { - float eul[3], quat[4]; + float quat[4]; +#ifdef USE_MATHUTILS_DEG + float eul[3]; int x; +#endif if(!BaseMath_ReadCallback(self)) return NULL; @@ -133,7 +128,7 @@ static PyObject *Euler_ToQuat(EulerObject * self) EulToQuat(self->eul, quat); #endif - return newQuaternionObject(quat, Py_NEW); + return newQuaternionObject(quat, Py_NEW, NULL); } //----------------------------Euler.toMatrix()--------------------- //return a matrix representation of the euler @@ -154,16 +149,17 @@ static PyObject *Euler_ToMatrix(EulerObject * self) #else EulToMat3(self->eul, (float (*)[3]) mat); #endif - return newMatrixObject(mat, 3, 3 , Py_NEW); + return newMatrixObject(mat, 3, 3 , Py_NEW, NULL); } //----------------------------Euler.unique()----------------------- //sets the x,y,z values to a unique euler rotation static PyObject *Euler_Unique(EulerObject * self) { +#define PI_2 (Py_PI * 2.0) +#define PI_HALF (Py_PI / 2.0) +#define PI_INV (1.0 / Py_PI) + double heading, pitch, bank; - double pi2 = Py_PI * 2.0f; - double piO2 = Py_PI / 2.0f; - double Opi2 = 1.0f / pi2; if(!BaseMath_ReadCallback(self)) return NULL; @@ -173,35 +169,39 @@ static PyObject *Euler_Unique(EulerObject * self) heading = self->eul[0] * (float)Py_PI / 180; pitch = self->eul[1] * (float)Py_PI / 180; bank = self->eul[2] * (float)Py_PI / 180; +#else + heading = self->eul[0]; + pitch = self->eul[1]; + bank = self->eul[2]; #endif //wrap heading in +180 / -180 pitch += Py_PI; - pitch -= floor(pitch * Opi2) * pi2; + pitch -= floor(pitch * PI_INV) * PI_2; pitch -= Py_PI; - if(pitch < -piO2) { + if(pitch < -PI_HALF) { pitch = -Py_PI - pitch; heading += Py_PI; bank += Py_PI; - } else if(pitch > piO2) { + } else if(pitch > PI_HALF) { pitch = Py_PI - pitch; heading += Py_PI; bank += Py_PI; } //gimbal lock test - if(fabs(pitch) > piO2 - 1e-4) { + if(fabs(pitch) > PI_HALF - 1e-4) { heading += bank; bank = 0.0f; } else { bank += Py_PI; - bank -= (floor(bank * Opi2)) * pi2; + bank -= (floor(bank * PI_INV)) * PI_2; bank -= Py_PI; } heading += Py_PI; - heading -= (floor(heading * Opi2)) * pi2; + heading -= (floor(heading * PI_INV)) * PI_2; heading -= Py_PI; #ifdef USE_MATHUTILS_DEG @@ -271,8 +271,10 @@ static PyObject *Euler_Rotate(EulerObject * self, PyObject *args) static PyObject *Euler_MakeCompatible(EulerObject * self, EulerObject *value) { +#ifdef USE_MATHUTILS_DEG float eul_from_rad[3]; int x; +#endif if(!EulerObject_Check(value)) { PyErr_SetString(PyExc_TypeError, "euler.makeCompatible(euler):expected a single euler argument."); @@ -311,7 +313,7 @@ static PyObject *Euler_copy(EulerObject * self, PyObject *args) if(!BaseMath_ReadCallback(self)) return NULL; - return newEulerObject(self->eul, Py_NEW); + return newEulerObject(self->eul, Py_NEW, Py_TYPE(self)); } //----------------------------print object (internal)-------------- @@ -376,8 +378,7 @@ static PyObject* Euler_richcmpr(PyObject *objectA, PyObject *objectB, int compar Py_RETURN_FALSE; } } -//------------------------tp_doc -static char EulerObject_doc[] = "This is a wrapper for euler objects."; + //---------------------SEQUENCE PROTOCOLS------------------------ //----------------------------len(object)------------------------ //sequence length @@ -460,7 +461,7 @@ static int Euler_ass_slice(EulerObject * self, int begin, int end, PyObject *e; if(!BaseMath_ReadCallback(self)) - return NULL; + return -1; CLAMP(begin, 0, 3); if (end<0) end= 4+end; @@ -562,8 +563,8 @@ PyTypeObject euler_Type = { 0, //tp_getattro 0, //tp_setattro 0, //tp_as_buffer - Py_TPFLAGS_DEFAULT, //tp_flags - EulerObject_doc, //tp_doc + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, //tp_flags + 0, //tp_doc 0, //tp_traverse 0, //tp_clear (richcmpfunc)Euler_richcmpr, //tp_richcompare @@ -596,12 +597,13 @@ PyTypeObject euler_Type = { (i.e. it was allocated elsewhere by MEM_mallocN()) pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON (i.e. it must be created here with PyMEM_malloc())*/ -PyObject *newEulerObject(float *eul, int type) +PyObject *newEulerObject(float *eul, int type, PyTypeObject *base_type) { EulerObject *self; int x; - self = PyObject_NEW(EulerObject, &euler_Type); + if(base_type) self = base_type->tp_alloc(base_type, 0); + else self = PyObject_NEW(EulerObject, &euler_Type); /* init callbacks as NULL */ self->cb_user= NULL; @@ -628,7 +630,7 @@ PyObject *newEulerObject(float *eul, int type) PyObject *newEulerObject_cb(PyObject *cb_user, int cb_type, int cb_subtype) { - EulerObject *self= (EulerObject *)newEulerObject(NULL, Py_NEW); + EulerObject *self= (EulerObject *)newEulerObject(NULL, Py_NEW, NULL); if(self) { Py_INCREF(cb_user); self->cb_user= cb_user; @@ -636,5 +638,5 @@ PyObject *newEulerObject_cb(PyObject *cb_user, int cb_type, int cb_subtype) self->cb_subtype= (unsigned char)cb_subtype; } - return self; + return (PyObject *)self; } diff --git a/source/blender/python/generic/euler.h b/source/blender/python/generic/euler.h index 0bff6de6964..a3706d53756 100644 --- a/source/blender/python/generic/euler.h +++ b/source/blender/python/generic/euler.h @@ -35,8 +35,7 @@ #include "../intern/bpy_compat.h" extern PyTypeObject euler_Type; - -#define EulerObject_Check(v) (Py_TYPE(v) == &euler_Type) +#define EulerObject_Check(_v) PyObject_TypeCheck((_v), &euler_Type) typedef struct { PyObject_VAR_HEAD @@ -55,7 +54,7 @@ be stored in py_data) or be a wrapper for data allocated through blender (stored in blend_data). This is an either/or struct not both*/ //prototypes -PyObject *newEulerObject( float *eul, int type ); +PyObject *newEulerObject( float *eul, int type, PyTypeObject *base_type); PyObject *newEulerObject_cb(PyObject *cb_user, int cb_type, int cb_subtype); #endif /* EXPP_euler_h */ diff --git a/source/blender/python/generic/matrix.c b/source/blender/python/generic/matrix.c index b546aa1226c..5bdbf804618 100644 --- a/source/blender/python/generic/matrix.c +++ b/source/blender/python/generic/matrix.c @@ -97,18 +97,6 @@ Mathutils_Callback mathutils_matrix_vector_cb = { /* matrix vector callbacks, this is so you can do matrix[i][j] = val */ /*-------------------------DOC STRINGS ---------------------------*/ -static char Matrix_Zero_doc[] = "() - set all values in the matrix to 0"; -static char Matrix_Identity_doc[] = "() - set the square matrix to it's identity matrix"; -static char Matrix_Transpose_doc[] = "() - set the matrix to it's transpose"; -static char Matrix_Determinant_doc[] = "() - return the determinant of the matrix"; -static char Matrix_Invert_doc[] = "() - set the matrix to it's inverse if an inverse is possible"; -static char Matrix_TranslationPart_doc[] = "() - return a vector encompassing the translation of the matrix"; -static char Matrix_RotationPart_doc[] = "() - return a vector encompassing the rotation of the matrix"; -static char Matrix_scalePart_doc[] = "() - convert matrix to a 3D vector"; -static char Matrix_Resize4x4_doc[] = "() - resize the matrix to a 4x4 square matrix"; -static char Matrix_toEuler_doc[] = "(eul_compat) - convert matrix to a euler angle rotation, optional euler argument that the new euler will be made compatible with."; -static char Matrix_toQuat_doc[] = "() - convert matrix to a quaternion rotation"; -static char Matrix_copy_doc[] = "() - return a copy of the matrix"; static PyObject *Matrix_Zero( MatrixObject * self ); static PyObject *Matrix_Identity( MatrixObject * self ); @@ -125,19 +113,19 @@ static PyObject *Matrix_copy( MatrixObject * self ); /*-----------------------METHOD DEFINITIONS ----------------------*/ static struct PyMethodDef Matrix_methods[] = { - {"zero", (PyCFunction) Matrix_Zero, METH_NOARGS, Matrix_Zero_doc}, - {"identity", (PyCFunction) Matrix_Identity, METH_NOARGS, Matrix_Identity_doc}, - {"transpose", (PyCFunction) Matrix_Transpose, METH_NOARGS, Matrix_Transpose_doc}, - {"determinant", (PyCFunction) Matrix_Determinant, METH_NOARGS, Matrix_Determinant_doc}, - {"invert", (PyCFunction) Matrix_Invert, METH_NOARGS, Matrix_Invert_doc}, - {"translationPart", (PyCFunction) Matrix_TranslationPart, METH_NOARGS, Matrix_TranslationPart_doc}, - {"rotationPart", (PyCFunction) Matrix_RotationPart, METH_NOARGS, Matrix_RotationPart_doc}, - {"scalePart", (PyCFunction) Matrix_scalePart, METH_NOARGS, Matrix_scalePart_doc}, - {"resize4x4", (PyCFunction) Matrix_Resize4x4, METH_NOARGS, Matrix_Resize4x4_doc}, - {"toEuler", (PyCFunction) Matrix_toEuler, METH_VARARGS, Matrix_toEuler_doc}, - {"toQuat", (PyCFunction) Matrix_toQuat, METH_NOARGS, Matrix_toQuat_doc}, - {"copy", (PyCFunction) Matrix_copy, METH_NOARGS, Matrix_copy_doc}, - {"__copy__", (PyCFunction) Matrix_copy, METH_NOARGS, Matrix_copy_doc}, + {"zero", (PyCFunction) Matrix_Zero, METH_NOARGS, NULL}, + {"identity", (PyCFunction) Matrix_Identity, METH_NOARGS, NULL}, + {"transpose", (PyCFunction) Matrix_Transpose, METH_NOARGS, NULL}, + {"determinant", (PyCFunction) Matrix_Determinant, METH_NOARGS, NULL}, + {"invert", (PyCFunction) Matrix_Invert, METH_NOARGS, NULL}, + {"translationPart", (PyCFunction) Matrix_TranslationPart, METH_NOARGS, NULL}, + {"rotationPart", (PyCFunction) Matrix_RotationPart, METH_NOARGS, NULL}, + {"scalePart", (PyCFunction) Matrix_scalePart, METH_NOARGS, NULL}, + {"resize4x4", (PyCFunction) Matrix_Resize4x4, METH_NOARGS, NULL}, + {"toEuler", (PyCFunction) Matrix_toEuler, METH_VARARGS, NULL}, + {"toQuat", (PyCFunction) Matrix_toQuat, METH_NOARGS, NULL}, + {"copy", (PyCFunction) Matrix_copy, METH_NOARGS, NULL}, + {"__copy__", (PyCFunction) Matrix_copy, METH_NOARGS, NULL}, {NULL, NULL, 0, NULL} }; @@ -158,7 +146,7 @@ static PyObject *Matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds) PyErr_SetString(PyExc_AttributeError, "Mathutils.Matrix(): expects 0-4 numeric sequences of the same size\n"); return NULL; } else if (argSize == 0) { //return empty 4D matrix - return (PyObject *) newMatrixObject(NULL, 4, 4, Py_NEW); + return (PyObject *) newMatrixObject(NULL, 4, 4, Py_NEW, NULL); }else if (argSize == 1){ //copy constructor for matrix objects argObject = PyTuple_GET_ITEM(args, 0); @@ -167,11 +155,7 @@ static PyObject *Matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds) if(!BaseMath_ReadCallback(mat)) return NULL; - argSize = mat->rowSize; //rows - seqSize = mat->colSize; //col - for(i = 0; i < (seqSize * argSize); i++){ - matrix[i] = mat->contigPtr[i]; - } + memcpy(matrix, mat->contigPtr, sizeof(float) * mat->rowSize * mat->colSize); } }else{ //2-4 arguments (all seqs? all same size?) for(i =0; i < argSize; i++){ @@ -216,7 +200,7 @@ static PyObject *Matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds) } } } - return newMatrixObject(matrix, argSize, seqSize, Py_NEW); + return newMatrixObject(matrix, argSize, seqSize, Py_NEW, NULL); } /*-----------------------------METHODS----------------------------*/ @@ -239,14 +223,16 @@ static PyObject *Matrix_toQuat(MatrixObject * self) Mat4ToQuat((float (*)[4])*self->matrix, quat); } - return newQuaternionObject(quat, Py_NEW); + return newQuaternionObject(quat, Py_NEW, NULL); } /*---------------------------Matrix.toEuler() --------------------*/ PyObject *Matrix_toEuler(MatrixObject * self, PyObject *args) { float eul[3], eul_compatf[3]; EulerObject *eul_compat = NULL; +#ifdef USE_MATHUTILS_DEG int x; +#endif if(!BaseMath_ReadCallback(self)) return NULL; @@ -288,7 +274,7 @@ PyObject *Matrix_toEuler(MatrixObject * self, PyObject *args) eul[x] *= (float) (180 / Py_PI); } #endif - return newEulerObject(eul, Py_NEW); + return newEulerObject(eul, Py_NEW, NULL); } /*---------------------------Matrix.resize4x4() ------------------*/ PyObject *Matrix_Resize4x4(MatrixObject * self) @@ -364,7 +350,7 @@ PyObject *Matrix_TranslationPart(MatrixObject * self) vec[1] = self->matrix[3][1]; vec[2] = self->matrix[3][2]; - return newVectorObject(vec, 3, Py_NEW); + return newVectorObject(vec, 3, Py_NEW, NULL); } /*---------------------------Matrix.rotationPart() ---------------*/ PyObject *Matrix_RotationPart(MatrixObject * self) @@ -390,7 +376,7 @@ PyObject *Matrix_RotationPart(MatrixObject * self) mat[7] = self->matrix[2][1]; mat[8] = self->matrix[2][2]; - return newMatrixObject(mat, 3, 3, Py_NEW); + return newMatrixObject(mat, 3, 3, Py_NEW, Py_TYPE(self)); } /*---------------------------Matrix.scalePart() --------------------*/ PyObject *Matrix_scalePart(MatrixObject * self) @@ -419,7 +405,7 @@ PyObject *Matrix_scalePart(MatrixObject * self) scale[0]= tmat[0][0]; scale[1]= tmat[1][1]; scale[2]= tmat[2][2]; - return newVectorObject(scale, 3, Py_NEW); + return newVectorObject(scale, 3, Py_NEW, NULL); } /*---------------------------Matrix.invert() ---------------------*/ PyObject *Matrix_Invert(MatrixObject * self) @@ -589,7 +575,7 @@ PyObject *Matrix_copy(MatrixObject * self) if(!BaseMath_ReadCallback(self)) return NULL; - return (PyObject*)(MatrixObject*)newMatrixObject((float (*))*self->matrix, self->rowSize, self->colSize, Py_NEW); + return (PyObject*)newMatrixObject((float (*))*self->matrix, self->rowSize, self->colSize, Py_NEW, Py_TYPE(self)); } /*----------------------------print object (internal)-------------*/ @@ -674,8 +660,7 @@ static PyObject* Matrix_richcmpr(PyObject *objectA, PyObject *objectB, int compa Py_RETURN_FALSE; } } -/*------------------------tp_doc*/ -static char MatrixObject_doc[] = "This is a wrapper for matrix objects."; + /*---------------------SEQUENCE PROTOCOLS------------------------ ----------------------------len(object)------------------------ sequence length*/ @@ -775,8 +760,7 @@ static PyObject *Matrix_slice(MatrixObject * self, int begin, int end) } /*----------------------------object[z:y]------------------------ sequence slice (set)*/ -static int Matrix_ass_slice(MatrixObject * self, int begin, int end, - PyObject * seq) +static int Matrix_ass_slice(MatrixObject * self, int begin, int end, PyObject * seq) { int i, x, y, size, sub_size = 0; float mat[16], f; @@ -882,7 +866,7 @@ static PyObject *Matrix_add(PyObject * m1, PyObject * m2) } } - return newMatrixObject(mat, mat1->rowSize, mat1->colSize, Py_NEW); + return newMatrixObject(mat, mat1->rowSize, mat1->colSize, Py_NEW, NULL); } /*------------------------obj - obj------------------------------ subtraction*/ @@ -915,7 +899,7 @@ static PyObject *Matrix_sub(PyObject * m1, PyObject * m2) } } - return newMatrixObject(mat, mat1->rowSize, mat1->colSize, Py_NEW); + return newMatrixObject(mat, mat1->rowSize, mat1->colSize, Py_NEW, NULL); } /*------------------------obj * obj------------------------------ mulplication*/ @@ -954,7 +938,7 @@ static PyObject *Matrix_mul(PyObject * m1, PyObject * m2) } } - return newMatrixObject(mat, mat1->rowSize, mat2->colSize, Py_NEW); + return newMatrixObject(mat, mat1->rowSize, mat2->colSize, Py_NEW, NULL); } if(mat1==NULL){ @@ -965,7 +949,7 @@ static PyObject *Matrix_mul(PyObject * m1, PyObject * m2) mat[((x * mat2->colSize) + y)] = scalar * mat2->matrix[x][y]; } } - return newMatrixObject(mat, mat2->rowSize, mat2->colSize, Py_NEW); + return newMatrixObject(mat, mat2->rowSize, mat2->colSize, Py_NEW, NULL); } PyErr_SetString(PyExc_TypeError, "Matrix multiplication: arguments not acceptable for this operation"); @@ -984,7 +968,7 @@ static PyObject *Matrix_mul(PyObject * m1, PyObject * m2) mat[((x * mat1->colSize) + y)] = scalar * mat1->matrix[x][y]; } } - return newMatrixObject(mat, mat1->rowSize, mat1->colSize, Py_NEW); + return newMatrixObject(mat, mat1->rowSize, mat1->colSize, Py_NEW, NULL); } } PyErr_SetString(PyExc_TypeError, "Matrix multiplication: arguments not acceptable for this operation"); @@ -1012,6 +996,123 @@ static PySequenceMethods Matrix_SeqMethods = { (ssizeobjargproc) Matrix_ass_item, /* sq_ass_item */ (ssizessizeobjargproc) Matrix_ass_slice, /* sq_ass_slice */ }; + + + +#if (PY_VERSION_HEX >= 0x03000000) +static PyObject *Matrix_subscript(MatrixObject* self, PyObject* item) +{ + if (PyIndex_Check(item)) { + Py_ssize_t i; + i = PyNumber_AsSsize_t(item, PyExc_IndexError); + if (i == -1 && PyErr_Occurred()) + return NULL; + if (i < 0) + i += self->rowSize; + return Matrix_item(self, i); + } else if (PySlice_Check(item)) { + Py_ssize_t start, stop, step, slicelength; + + if (PySlice_GetIndicesEx((PySliceObject*)item, self->rowSize, &start, &stop, &step, &slicelength) < 0) + return NULL; + + if (slicelength <= 0) { + return PyList_New(0); + } + else if (step == 1) { + return Matrix_slice(self, start, stop); + } + else { + PyErr_SetString(PyExc_TypeError, "slice steps not supported with matricies"); + return NULL; + } + } + else { + PyErr_Format(PyExc_TypeError, + "vector indices must be integers, not %.200s", + item->ob_type->tp_name); + return NULL; + } +} + +static int Matrix_ass_subscript(MatrixObject* self, PyObject* item, PyObject* value) +{ + if (PyIndex_Check(item)) { + Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); + if (i == -1 && PyErr_Occurred()) + return -1; + if (i < 0) + i += self->rowSize; + return Matrix_ass_item(self, i, value); + } + else if (PySlice_Check(item)) { + Py_ssize_t start, stop, step, slicelength; + + if (PySlice_GetIndicesEx((PySliceObject*)item, self->rowSize, &start, &stop, &step, &slicelength) < 0) + return -1; + + if (step == 1) + return Matrix_ass_slice(self, start, stop, value); + else { + PyErr_SetString(PyExc_TypeError, "slice steps not supported with matricies"); + return -1; + } + } + else { + PyErr_Format(PyExc_TypeError, + "matrix indices must be integers, not %.200s", + item->ob_type->tp_name); + return -1; + } +} + +static PyMappingMethods Matrix_AsMapping = { + (lenfunc)Matrix_len, + (binaryfunc)Matrix_subscript, + (objobjargproc)Matrix_ass_subscript +}; +#endif /* (PY_VERSION_HEX >= 0x03000000) */ + + + +#if (PY_VERSION_HEX >= 0x03000000) +static PyNumberMethods Matrix_NumMethods = { + (binaryfunc) Matrix_add, /*nb_add*/ + (binaryfunc) Matrix_sub, /*nb_subtract*/ + (binaryfunc) Matrix_mul, /*nb_multiply*/ + 0, /*nb_remainder*/ + 0, /*nb_divmod*/ + 0, /*nb_power*/ + (unaryfunc) 0, /*nb_negative*/ + (unaryfunc) 0, /*tp_positive*/ + (unaryfunc) 0, /*tp_absolute*/ + (inquiry) 0, /*tp_bool*/ + (unaryfunc) Matrix_inv, /*nb_invert*/ + 0, /*nb_lshift*/ + (binaryfunc)0, /*nb_rshift*/ + 0, /*nb_and*/ + 0, /*nb_xor*/ + 0, /*nb_or*/ + 0, /*nb_int*/ + 0, /*nb_reserved*/ + 0, /*nb_float*/ + 0, /* nb_inplace_add */ + 0, /* nb_inplace_subtract */ + 0, /* nb_inplace_multiply */ + 0, /* nb_inplace_remainder */ + 0, /* nb_inplace_power */ + 0, /* nb_inplace_lshift */ + 0, /* nb_inplace_rshift */ + 0, /* nb_inplace_and */ + 0, /* nb_inplace_xor */ + 0, /* nb_inplace_or */ + 0, /* nb_floor_divide */ + 0, /* nb_true_divide */ + 0, /* nb_inplace_floor_divide */ + 0, /* nb_inplace_true_divide */ + 0, /* nb_index */ +}; +#else static PyNumberMethods Matrix_NumMethods = { (binaryfunc) Matrix_add, /* __add__ */ (binaryfunc) Matrix_sub, /* __sub__ */ @@ -1037,6 +1138,7 @@ static PyNumberMethods Matrix_NumMethods = { (unaryfunc) 0, /* __oct__ */ (unaryfunc) 0, /* __hex__ */ }; +#endif static PyObject *Matrix_getRowSize( MatrixObject * self, void *type ) { @@ -1080,15 +1182,19 @@ PyTypeObject matrix_Type = { (reprfunc) Matrix_repr, /*tp_repr*/ &Matrix_NumMethods, /*tp_as_number*/ &Matrix_SeqMethods, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ +#if (PY_VERSION_HEX >= 0x03000000) + &Matrix_AsMapping, /*tp_as_mapping*/ +#else + 0, +#endif 0, /*tp_hash*/ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - MatrixObject_doc, /*tp_doc*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + 0, /*tp_doc*/ 0, /*tp_traverse*/ 0, /*tp_clear*/ (richcmpfunc)Matrix_richcmpr, /*tp_richcompare*/ @@ -1132,7 +1238,7 @@ self->matrix[1][1] = self->contigPtr[4] */ (i.e. it was allocated elsewhere by MEM_mallocN()) pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON (i.e. it must be created here with PyMEM_malloc())*/ -PyObject *newMatrixObject(float *mat, int rowSize, int colSize, int type) +PyObject *newMatrixObject(float *mat, int rowSize, int colSize, int type, PyTypeObject *base_type) { MatrixObject *self; int x, row, col; @@ -1143,7 +1249,9 @@ PyObject *newMatrixObject(float *mat, int rowSize, int colSize, int type) return NULL; } - self = PyObject_NEW(MatrixObject, &matrix_Type); + if(base_type) self = (MatrixObject *)base_type->tp_alloc(base_type, 0); + else self = PyObject_NEW(MatrixObject, &matrix_Type); + self->rowSize = rowSize; self->colSize = colSize; @@ -1201,7 +1309,7 @@ PyObject *newMatrixObject(float *mat, int rowSize, int colSize, int type) PyObject *newMatrixObject_cb(PyObject *cb_user, int rowSize, int colSize, int cb_type, int cb_subtype) { - MatrixObject *self= (MatrixObject *)newMatrixObject(NULL, rowSize, colSize, Py_NEW); + MatrixObject *self= (MatrixObject *)newMatrixObject(NULL, rowSize, colSize, Py_NEW, NULL); if(self) { Py_INCREF(cb_user); self->cb_user= cb_user; @@ -1246,5 +1354,5 @@ static PyObject *column_vector_multiplication(MatrixObject * mat, VectorObject* vecNew[z++] = (float)dot; dot = 0.0f; } - return newVectorObject(vecNew, vec->size, Py_NEW); + return newVectorObject(vecNew, vec->size, Py_NEW, NULL); } diff --git a/source/blender/python/generic/matrix.h b/source/blender/python/generic/matrix.h index 4b073668969..856c711c4ef 100644 --- a/source/blender/python/generic/matrix.h +++ b/source/blender/python/generic/matrix.h @@ -33,8 +33,7 @@ #include extern PyTypeObject matrix_Type; - -#define MatrixObject_Check(v) ((v)->ob_type == &matrix_Type) +#define MatrixObject_Check(_v) PyObject_TypeCheck((_v), &matrix_Type) typedef float **ptRow; typedef struct _Matrix { /* keep aligned with BaseMathObject in Mathutils.h */ @@ -58,7 +57,7 @@ be stored in py_data) or be a wrapper for data allocated through blender (stored in blend_data). This is an either/or struct not both*/ /*prototypes*/ -PyObject *newMatrixObject(float *mat, int rowSize, int colSize, int type); +PyObject *newMatrixObject(float *mat, int rowSize, int colSize, int type, PyTypeObject *base_type); PyObject *newMatrixObject_cb(PyObject *user, int rowSize, int colSize, int cb_type, int cb_subtype); extern int mathutils_matrix_vector_cb_index; diff --git a/source/blender/python/generic/quat.c b/source/blender/python/generic/quat.c index c004bcd1bf2..b9c491e24e4 100644 --- a/source/blender/python/generic/quat.c +++ b/source/blender/python/generic/quat.c @@ -34,16 +34,6 @@ //-------------------------DOC STRINGS --------------------------- -static char Quaternion_Identity_doc[] = "() - set the quaternion to it's identity (1, vector)"; -static char Quaternion_Negate_doc[] = "() - set all values in the quaternion to their negative"; -static char Quaternion_Conjugate_doc[] = "() - set the quaternion to it's conjugate"; -static char Quaternion_Inverse_doc[] = "() - set the quaternion to it's inverse"; -static char Quaternion_Normalize_doc[] = "() - normalize the vector portion of the quaternion"; -static char Quaternion_ToEuler_doc[] = "(eul_compat) - return a euler rotation representing the quaternion, optional euler argument that the new euler will be made compatible with."; -static char Quaternion_ToMatrix_doc[] = "() - return a rotation matrix representing the quaternion"; -static char Quaternion_Cross_doc[] = "(other) - return the cross product between this quaternion and another"; -static char Quaternion_Dot_doc[] = "(other) - return the dot product between this quaternion and another"; -static char Quaternion_copy_doc[] = "() - return a copy of the quat"; static PyObject *Quaternion_Identity( QuaternionObject * self ); static PyObject *Quaternion_Negate( QuaternionObject * self ); @@ -58,17 +48,17 @@ static PyObject *Quaternion_copy( QuaternionObject * self ); //-----------------------METHOD DEFINITIONS ---------------------- static struct PyMethodDef Quaternion_methods[] = { - {"identity", (PyCFunction) Quaternion_Identity, METH_NOARGS, Quaternion_Identity_doc}, - {"negate", (PyCFunction) Quaternion_Negate, METH_NOARGS, Quaternion_Negate_doc}, - {"conjugate", (PyCFunction) Quaternion_Conjugate, METH_NOARGS, Quaternion_Conjugate_doc}, - {"inverse", (PyCFunction) Quaternion_Inverse, METH_NOARGS, Quaternion_Inverse_doc}, - {"normalize", (PyCFunction) Quaternion_Normalize, METH_NOARGS, Quaternion_Normalize_doc}, - {"toEuler", (PyCFunction) Quaternion_ToEuler, METH_VARARGS, Quaternion_ToEuler_doc}, - {"toMatrix", (PyCFunction) Quaternion_ToMatrix, METH_NOARGS, Quaternion_ToMatrix_doc}, - {"cross", (PyCFunction) Quaternion_Cross, METH_O, Quaternion_Cross_doc}, - {"dot", (PyCFunction) Quaternion_Dot, METH_O, Quaternion_Dot_doc}, - {"__copy__", (PyCFunction) Quaternion_copy, METH_NOARGS, Quaternion_copy_doc}, - {"copy", (PyCFunction) Quaternion_copy, METH_NOARGS, Quaternion_copy_doc}, + {"identity", (PyCFunction) Quaternion_Identity, METH_NOARGS, NULL}, + {"negate", (PyCFunction) Quaternion_Negate, METH_NOARGS, NULL}, + {"conjugate", (PyCFunction) Quaternion_Conjugate, METH_NOARGS, NULL}, + {"inverse", (PyCFunction) Quaternion_Inverse, METH_NOARGS, NULL}, + {"normalize", (PyCFunction) Quaternion_Normalize, METH_NOARGS, NULL}, + {"toEuler", (PyCFunction) Quaternion_ToEuler, METH_VARARGS, NULL}, + {"toMatrix", (PyCFunction) Quaternion_ToMatrix, METH_NOARGS, NULL}, + {"cross", (PyCFunction) Quaternion_Cross, METH_O, NULL}, + {"dot", (PyCFunction) Quaternion_Dot, METH_O, NULL}, + {"__copy__", (PyCFunction) Quaternion_copy, METH_NOARGS, NULL}, + {"copy", (PyCFunction) Quaternion_copy, METH_NOARGS, NULL}, {NULL, NULL, 0, NULL} }; @@ -127,7 +117,7 @@ static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kw } } } else if (size == 0) { //returns a new empty quat - return newQuaternionObject(NULL, Py_NEW); + return newQuaternionObject(NULL, Py_NEW, NULL); } else { listObject = args; } @@ -167,7 +157,7 @@ static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kw AxisAngleToQuat(quat, quat, angle); #endif - return newQuaternionObject(quat, Py_NEW); + return newQuaternionObject(quat, Py_NEW, NULL); } //-----------------------------METHODS------------------------------ @@ -211,7 +201,7 @@ static PyObject *Quaternion_ToEuler(QuaternionObject * self, PyObject *args) eul[x] *= (180 / (float)Py_PI); } #endif - return newEulerObject(eul, Py_NEW); + return newEulerObject(eul, Py_NEW, NULL); } //----------------------------Quaternion.toMatrix()------------------ //return the quat as a matrix @@ -223,7 +213,7 @@ static PyObject *Quaternion_ToMatrix(QuaternionObject * self) return NULL; QuatToMat3(self->quat, (float (*)[3]) mat); - return newMatrixObject(mat, 3, 3, Py_NEW); + return newMatrixObject(mat, 3, 3, Py_NEW, NULL); } //----------------------------Quaternion.cross(other)------------------ @@ -241,7 +231,7 @@ static PyObject *Quaternion_Cross(QuaternionObject * self, QuaternionObject * va return NULL; QuatMul(quat, self->quat, value->quat); - return newQuaternionObject(quat, Py_NEW); + return newQuaternionObject(quat, Py_NEW, NULL); } //----------------------------Quaternion.dot(other)------------------ @@ -331,7 +321,7 @@ static PyObject *Quaternion_copy(QuaternionObject * self) if(!BaseMath_ReadCallback(self)) return NULL; - return newQuaternionObject(self->quat, Py_NEW); + return newQuaternionObject(self->quat, Py_NEW, Py_TYPE(self)); } //----------------------------print object (internal)-------------- @@ -394,8 +384,7 @@ static PyObject* Quaternion_richcmpr(PyObject *objectA, PyObject *objectB, int c Py_RETURN_FALSE; } } -//------------------------tp_doc -static char QuaternionObject_doc[] = "This is a wrapper for quaternion objects."; + //---------------------SEQUENCE PROTOCOLS------------------------ //----------------------------len(object)------------------------ //sequence length @@ -529,7 +518,7 @@ static PyObject *Quaternion_add(PyObject * q1, PyObject * q2) return NULL; QuatAdd(quat, quat1->quat, quat2->quat, 1.0f); - return newQuaternionObject(quat, Py_NEW); + return newQuaternionObject(quat, Py_NEW, NULL); } //------------------------obj - obj------------------------------ //subtraction @@ -554,7 +543,7 @@ static PyObject *Quaternion_sub(PyObject * q1, PyObject * q2) quat[x] = quat1->quat[x] - quat2->quat[x]; } - return newQuaternionObject(quat, Py_NEW); + return newQuaternionObject(quat, Py_NEW, NULL); } //------------------------obj * obj------------------------------ //mulplication @@ -585,7 +574,7 @@ static PyObject *Quaternion_mul(PyObject * q1, PyObject * q2) if ((scalar == -1.0 && PyErr_Occurred())==0) { /* FLOAT*QUAT */ QUATCOPY(quat, quat2->quat); QuatMulf(quat, scalar); - return newQuaternionObject(quat, Py_NEW); + return newQuaternionObject(quat, Py_NEW, NULL); } PyErr_SetString(PyExc_TypeError, "Quaternion multiplication: val * quat, val is not an acceptable type"); return NULL; @@ -604,7 +593,7 @@ static PyObject *Quaternion_mul(PyObject * q1, PyObject * q2) if ((scalar == -1.0 && PyErr_Occurred())==0) { /* QUAT*FLOAT */ QUATCOPY(quat, quat1->quat); QuatMulf(quat, scalar); - return newQuaternionObject(quat, Py_NEW); + return newQuaternionObject(quat, Py_NEW, NULL); } } @@ -622,6 +611,45 @@ static PySequenceMethods Quaternion_SeqMethods = { (ssizeobjargproc) Quaternion_ass_item, /* sq_ass_item */ (ssizessizeobjargproc) Quaternion_ass_slice, /* sq_ass_slice */ }; + +#if (PY_VERSION_HEX >= 0x03000000) +static PyNumberMethods Quaternion_NumMethods = { + (binaryfunc) Quaternion_add, /*nb_add*/ + (binaryfunc) Quaternion_sub, /*nb_subtract*/ + (binaryfunc) Quaternion_mul, /*nb_multiply*/ + 0, /*nb_remainder*/ + 0, /*nb_divmod*/ + 0, /*nb_power*/ + (unaryfunc) 0, /*nb_negative*/ + (unaryfunc) 0, /*tp_positive*/ + (unaryfunc) 0, /*tp_absolute*/ + (inquiry) 0, /*tp_bool*/ + (unaryfunc) 0, /*nb_invert*/ + 0, /*nb_lshift*/ + (binaryfunc)0, /*nb_rshift*/ + 0, /*nb_and*/ + 0, /*nb_xor*/ + 0, /*nb_or*/ + 0, /*nb_int*/ + 0, /*nb_reserved*/ + 0, /*nb_float*/ + 0, /* nb_inplace_add */ + 0, /* nb_inplace_subtract */ + 0, /* nb_inplace_multiply */ + 0, /* nb_inplace_remainder */ + 0, /* nb_inplace_power */ + 0, /* nb_inplace_lshift */ + 0, /* nb_inplace_rshift */ + 0, /* nb_inplace_and */ + 0, /* nb_inplace_xor */ + 0, /* nb_inplace_or */ + 0, /* nb_floor_divide */ + 0, /* nb_true_divide */ + 0, /* nb_inplace_floor_divide */ + 0, /* nb_inplace_true_divide */ + 0, /* nb_index */ +}; +#else static PyNumberMethods Quaternion_NumMethods = { (binaryfunc) Quaternion_add, /* __add__ */ (binaryfunc) Quaternion_sub, /* __sub__ */ @@ -646,9 +674,8 @@ static PyNumberMethods Quaternion_NumMethods = { (unaryfunc) 0, /* __float__ */ (unaryfunc) 0, /* __oct__ */ (unaryfunc) 0, /* __hex__ */ - }; - +#endif static PyObject *Quaternion_getAxis( QuaternionObject * self, void *type ) { @@ -692,7 +719,7 @@ static PyObject *Quaternion_getAxisVec( QuaternionObject * self, void *type ) EXPP_FloatsAreEqual(vec[2], 0.0f, 10) ){ vec[0] = 1.0f; } - return (PyObject *) newVectorObject(vec, 3, Py_NEW); + return (PyObject *) newVectorObject(vec, 3, Py_NEW, NULL); } @@ -768,8 +795,8 @@ PyTypeObject quaternion_Type = { 0, //tp_getattro 0, //tp_setattro 0, //tp_as_buffer - Py_TPFLAGS_DEFAULT, //tp_flags - QuaternionObject_doc, //tp_doc + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, //tp_flags + 0, //tp_doc 0, //tp_traverse 0, //tp_clear (richcmpfunc)Quaternion_richcmpr, //tp_richcompare @@ -802,11 +829,12 @@ PyTypeObject quaternion_Type = { (i.e. it was allocated elsewhere by MEM_mallocN()) pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON (i.e. it must be created here with PyMEM_malloc())*/ -PyObject *newQuaternionObject(float *quat, int type) +PyObject *newQuaternionObject(float *quat, int type, PyTypeObject *base_type) { QuaternionObject *self; - self = PyObject_NEW(QuaternionObject, &quaternion_Type); + if(base_type) self = base_type->tp_alloc(base_type, 0); + else self = PyObject_NEW(QuaternionObject, &quaternion_Type); /* init callbacks as NULL */ self->cb_user= NULL; @@ -831,7 +859,7 @@ PyObject *newQuaternionObject(float *quat, int type) PyObject *newQuaternionObject_cb(PyObject *cb_user, int cb_type, int cb_subtype) { - QuaternionObject *self= (QuaternionObject *)newQuaternionObject(NULL, Py_NEW); + QuaternionObject *self= (QuaternionObject *)newQuaternionObject(NULL, Py_NEW, NULL); if(self) { Py_INCREF(cb_user); self->cb_user= cb_user; diff --git a/source/blender/python/generic/quat.h b/source/blender/python/generic/quat.h index 2e74b5fa7f9..a7cfb7898b1 100644 --- a/source/blender/python/generic/quat.h +++ b/source/blender/python/generic/quat.h @@ -35,8 +35,7 @@ #include "../intern/bpy_compat.h" extern PyTypeObject quaternion_Type; - -#define QuaternionObject_Check(v) (Py_TYPE(v) == &quaternion_Type) +#define QuaternionObject_Check(_v) PyObject_TypeCheck((_v), &quaternion_Type) typedef struct { /* keep aligned with BaseMathObject in Mathutils.h */ PyObject_VAR_HEAD @@ -55,7 +54,7 @@ be stored in py_data) or be a wrapper for data allocated through blender (stored in blend_data). This is an either/or struct not both*/ //prototypes -PyObject *newQuaternionObject( float *quat, int type ); +PyObject *newQuaternionObject( float *quat, int type, PyTypeObject *base_type); PyObject *newQuaternionObject_cb(PyObject *cb_user, int cb_type, int cb_subtype); #endif /* EXPP_quat_h */ diff --git a/source/blender/python/generic/vector.c b/source/blender/python/generic/vector.c index 9ce0a7ca2f9..b4c74787e05 100644 --- a/source/blender/python/generic/vector.c +++ b/source/blender/python/generic/vector.c @@ -41,19 +41,6 @@ static PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat); /* utility func */ -/*-------------------------DOC STRINGS ---------------------------*/ -static char Vector_Zero_doc[] = "() - set all values in the vector to 0"; -static char Vector_Normalize_doc[] = "() - normalize the vector"; -static char Vector_Negate_doc[] = "() - changes vector to it's additive inverse"; -static char Vector_Resize2D_doc[] = "() - resize a vector to [x,y]"; -static char Vector_Resize3D_doc[] = "() - resize a vector to [x,y,z]"; -static char Vector_Resize4D_doc[] = "() - resize a vector to [x,y,z,w]"; -static char Vector_ToTrackQuat_doc[] = "(track, up) - extract a quaternion from the vector and the track and up axis"; -static char Vector_Reflect_doc[] = "(mirror) - return a vector reflected on the mirror normal"; -static char Vector_Cross_doc[] = "(other) - return the cross product between this vector and another"; -static char Vector_Dot_doc[] = "(other) - return the dot product between this vector and another"; -static char Vector_copy_doc[] = "() - return a copy of the vector"; -static char Vector_swizzle_doc[] = "Swizzle: Get or set axes in specified order"; /*-----------------------METHOD DEFINITIONS ----------------------*/ static PyObject *Vector_Zero( VectorObject * self ); static PyObject *Vector_Normalize( VectorObject * self ); @@ -68,18 +55,18 @@ static PyObject *Vector_Dot( VectorObject * self, VectorObject * value ); static PyObject *Vector_copy( VectorObject * self ); static struct PyMethodDef Vector_methods[] = { - {"zero", (PyCFunction) Vector_Zero, METH_NOARGS, Vector_Zero_doc}, - {"normalize", (PyCFunction) Vector_Normalize, METH_NOARGS, Vector_Normalize_doc}, - {"negate", (PyCFunction) Vector_Negate, METH_NOARGS, Vector_Negate_doc}, - {"resize2D", (PyCFunction) Vector_Resize2D, METH_NOARGS, Vector_Resize2D_doc}, - {"resize3D", (PyCFunction) Vector_Resize3D, METH_NOARGS, Vector_Resize3D_doc}, - {"resize4D", (PyCFunction) Vector_Resize4D, METH_NOARGS, Vector_Resize4D_doc}, - {"toTrackQuat", ( PyCFunction ) Vector_ToTrackQuat, METH_VARARGS, Vector_ToTrackQuat_doc}, - {"reflect", ( PyCFunction ) Vector_Reflect, METH_O, Vector_Reflect_doc}, - {"cross", ( PyCFunction ) Vector_Cross, METH_O, Vector_Dot_doc}, - {"dot", ( PyCFunction ) Vector_Dot, METH_O, Vector_Cross_doc}, - {"copy", (PyCFunction) Vector_copy, METH_NOARGS, Vector_copy_doc}, - {"__copy__", (PyCFunction) Vector_copy, METH_NOARGS, Vector_copy_doc}, + {"zero", (PyCFunction) Vector_Zero, METH_NOARGS, NULL}, + {"normalize", (PyCFunction) Vector_Normalize, METH_NOARGS, NULL}, + {"negate", (PyCFunction) Vector_Negate, METH_NOARGS, NULL}, + {"resize2D", (PyCFunction) Vector_Resize2D, METH_NOARGS, NULL}, + {"resize3D", (PyCFunction) Vector_Resize3D, METH_NOARGS, NULL}, + {"resize4D", (PyCFunction) Vector_Resize4D, METH_NOARGS, NULL}, + {"toTrackQuat", ( PyCFunction ) Vector_ToTrackQuat, METH_VARARGS, NULL}, + {"reflect", ( PyCFunction ) Vector_Reflect, METH_O, NULL}, + {"cross", ( PyCFunction ) Vector_Cross, METH_O, NULL}, + {"dot", ( PyCFunction ) Vector_Dot, METH_O, NULL}, + {"copy", (PyCFunction) Vector_copy, METH_NOARGS, NULL}, + {"__copy__", (PyCFunction) Vector_copy, METH_NOARGS, NULL}, {NULL, NULL, 0, NULL} }; @@ -104,7 +91,7 @@ static PyObject *Vector_new(PyTypeObject *type, PyObject *args, PyObject *kwds) } } else if (size == 0) { //returns a new empty 3d vector - return newVectorObject(NULL, 3, Py_NEW); + return newVectorObject(NULL, 3, Py_NEW, type); } else { listObject = args; } @@ -131,7 +118,7 @@ static PyObject *Vector_new(PyTypeObject *type, PyObject *args, PyObject *kwds) vec[i]= f; Py_DECREF(v); } - return newVectorObject(vec, size, Py_NEW); + return newVectorObject(vec, size, Py_NEW, type); } /*-----------------------------METHODS---------------------------- */ @@ -362,7 +349,7 @@ static PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args ) vectoquat(vec, track, up, quat); - return newQuaternionObject(quat, Py_NEW); + return newQuaternionObject(quat, Py_NEW, NULL); } /*----------------------------Vector.reflect(mirror) ---------------------- @@ -414,7 +401,7 @@ static PyObject *Vector_Reflect( VectorObject * self, VectorObject * value ) reflect[1] = (dot2 * mirror[1]) - vec[1]; reflect[2] = (dot2 * mirror[2]) - vec[2]; - return newVectorObject(reflect, self->size, Py_NEW); + return newVectorObject(reflect, self->size, Py_NEW, NULL); } static PyObject *Vector_Cross( VectorObject * self, VectorObject * value ) @@ -434,7 +421,7 @@ static PyObject *Vector_Cross( VectorObject * self, VectorObject * value ) if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value)) return NULL; - vecCross = (VectorObject *)newVectorObject(NULL, 3, Py_NEW); + vecCross = (VectorObject *)newVectorObject(NULL, 3, Py_NEW, NULL); Crossf(vecCross->vec, self->vec, value->vec); return (PyObject *)vecCross; } @@ -470,7 +457,7 @@ static PyObject *Vector_copy(VectorObject * self) if(!BaseMath_ReadCallback(self)) return NULL; - return newVectorObject(self->vec, self->size, Py_NEW); + return newVectorObject(self->vec, self->size, Py_NEW, Py_TYPE(self)); } /*----------------------------print object (internal)------------- @@ -647,7 +634,7 @@ static PyObject *Vector_add(PyObject * v1, PyObject * v2) for(i = 0; i < vec1->size; i++) { vec[i] = vec1->vec[i] + vec2->vec[i]; } - return newVectorObject(vec, vec1->size, Py_NEW); + return newVectorObject(vec, vec1->size, Py_NEW, NULL); } PyErr_SetString(PyExc_AttributeError, "Vector addition: arguments not valid for this operation....\n"); @@ -717,7 +704,7 @@ static PyObject *Vector_sub(PyObject * v1, PyObject * v2) vec[i] = vec1->vec[i] - vec2->vec[i]; } - return newVectorObject(vec, vec1->size, Py_NEW); + return newVectorObject(vec, vec1->size, Py_NEW, NULL); } /*------------------------obj -= obj------------------------------ @@ -812,7 +799,7 @@ static PyObject *Vector_mul(PyObject * v1, PyObject * v2) for(i = 0; i < vec1->size; i++) { vec[i] = vec1->vec[i] * scalar; } - return newVectorObject(vec, vec1->size, Py_NEW); + return newVectorObject(vec, vec1->size, Py_NEW, NULL); } @@ -912,7 +899,7 @@ static PyObject *Vector_div(PyObject * v1, PyObject * v2) for(i = 0; i < vec1->size; i++) { vec[i] = vec1->vec[i] / scalar; } - return newVectorObject(vec, vec1->size, Py_NEW); + return newVectorObject(vec, vec1->size, Py_NEW, NULL); } /*------------------------obj /= obj------------------------------ @@ -960,11 +947,9 @@ static PyObject *Vector_neg(VectorObject *self) vec[i] = -self->vec[i]; } - return newVectorObject(vec, self->size, Py_NEW); + return newVectorObject(vec, self->size, Py_NEW, Py_TYPE(self)); } -/*------------------------tp_doc*/ -static char VectorObject_doc[] = "This is a wrapper for vector objects."; /*------------------------vec_magnitude_nosqrt (internal) - for comparing only */ static double vec_magnitude_nosqrt(float *data, int size) { @@ -1066,17 +1051,139 @@ static PyObject* Vector_richcmpr(PyObject *objectA, PyObject *objectB, int compa Py_RETURN_FALSE; } } + /*-----------------PROTCOL DECLARATIONS--------------------------*/ static PySequenceMethods Vector_SeqMethods = { (inquiry) Vector_len, /* sq_length */ (binaryfunc) 0, /* sq_concat */ - (ssizeargfunc) 0, /* sq_repeat */ + (ssizeargfunc) 0, /* sq_repeat */ (ssizeargfunc) Vector_item, /* sq_item */ - (ssizessizeargfunc) Vector_slice, /* sq_slice */ +#if (PY_VERSION_HEX < 0x03000000) + (ssizessizeargfunc) Vector_slice, /* sq_slice */ /* PY2 ONLY */ +#else + NULL, +#endif (ssizeobjargproc) Vector_ass_item, /* sq_ass_item */ - (ssizessizeobjargproc) Vector_ass_slice, /* sq_ass_slice */ +#if (PY_VERSION_HEX < 0x03000000) + (ssizessizeobjargproc) Vector_ass_slice, /* sq_ass_slice */ /* PY2 ONLY */ +#else + NULL, +#endif }; + + +#if (PY_VERSION_HEX >= 0x03000000) +static PyObject *Vector_subscript(VectorObject* self, PyObject* item) +{ + if (PyIndex_Check(item)) { + Py_ssize_t i; + i = PyNumber_AsSsize_t(item, PyExc_IndexError); + if (i == -1 && PyErr_Occurred()) + return NULL; + if (i < 0) + i += self->size; + return Vector_item(self, i); + } else if (PySlice_Check(item)) { + Py_ssize_t start, stop, step, slicelength; + + if (PySlice_GetIndicesEx((PySliceObject*)item, self->size, &start, &stop, &step, &slicelength) < 0) + return NULL; + + if (slicelength <= 0) { + return PyList_New(0); + } + else if (step == 1) { + return Vector_slice(self, start, stop); + } + else { + PyErr_SetString(PyExc_TypeError, "slice steps not supported with vectors"); + return NULL; + } + } + else { + PyErr_Format(PyExc_TypeError, + "vector indices must be integers, not %.200s", + item->ob_type->tp_name); + return NULL; + } +} + +static int Vector_ass_subscript(VectorObject* self, PyObject* item, PyObject* value) +{ + if (PyIndex_Check(item)) { + Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); + if (i == -1 && PyErr_Occurred()) + return -1; + if (i < 0) + i += self->size; + return Vector_ass_item(self, i, value); + } + else if (PySlice_Check(item)) { + Py_ssize_t start, stop, step, slicelength; + + if (PySlice_GetIndicesEx((PySliceObject*)item, self->size, &start, &stop, &step, &slicelength) < 0) + return -1; + + if (step == 1) + return Vector_ass_slice(self, start, stop, value); + else { + PyErr_SetString(PyExc_TypeError, "slice steps not supported with vectors"); + return -1; + } + } + else { + PyErr_Format(PyExc_TypeError, + "vector indices must be integers, not %.200s", + item->ob_type->tp_name); + return -1; + } +} + +static PyMappingMethods Vector_AsMapping = { + (lenfunc)Vector_len, + (binaryfunc)Vector_subscript, + (objobjargproc)Vector_ass_subscript +}; +#endif /* (PY_VERSION_HEX >= 0x03000000) */ +#if (PY_VERSION_HEX >= 0x03000000) +static PyNumberMethods Vector_NumMethods = { + (binaryfunc) Vector_add, /*nb_add*/ + (binaryfunc) Vector_sub, /*nb_subtract*/ + (binaryfunc) Vector_mul, /*nb_multiply*/ + 0, /*nb_remainder*/ + 0, /*nb_divmod*/ + 0, /*nb_power*/ + (unaryfunc) Vector_neg, /*nb_negative*/ + (unaryfunc) 0, /*tp_positive*/ + (unaryfunc) 0, /*tp_absolute*/ + (inquiry) 0, /*tp_bool*/ + (unaryfunc) 0, /*nb_invert*/ + 0, /*nb_lshift*/ + (binaryfunc)0, /*nb_rshift*/ + 0, /*nb_and*/ + 0, /*nb_xor*/ + 0, /*nb_or*/ + 0, /*nb_int*/ + 0, /*nb_reserved*/ + 0, /*nb_float*/ + Vector_iadd, /* nb_inplace_add */ + Vector_isub, /* nb_inplace_subtract */ + Vector_imul, /* nb_inplace_multiply */ + 0, /* nb_inplace_remainder */ + 0, /* nb_inplace_power */ + 0, /* nb_inplace_lshift */ + 0, /* nb_inplace_rshift */ + 0, /* nb_inplace_and */ + 0, /* nb_inplace_xor */ + 0, /* nb_inplace_or */ + 0, /* nb_floor_divide */ + Vector_div, /* nb_true_divide */ + 0, /* nb_inplace_floor_divide */ + Vector_idiv, /* nb_inplace_true_divide */ + 0, /* nb_index */ +}; +#else static PyNumberMethods Vector_NumMethods = { (binaryfunc) Vector_add, /* __add__ */ (binaryfunc) Vector_sub, /* __sub__ */ @@ -1122,6 +1229,8 @@ static PyNumberMethods Vector_NumMethods = { (binaryfunc) NULL, /*__ifloordiv__*/ (binaryfunc) NULL, /*__itruediv__*/ }; +#endif + /*------------------PY_OBECT DEFINITION--------------------------*/ /* @@ -1225,7 +1334,7 @@ static PyObject *Vector_getSwizzle(VectorObject * self, void *closure) axisA++; } - return newVectorObject(vec, axisA, Py_NEW); + return newVectorObject(vec, axisA, Py_NEW, Py_TYPE(self)); } /* Set the items of this vector using a swizzle. @@ -1373,342 +1482,342 @@ static PyGetSetDef Vector_getseters[] = { NULL}, /* autogenerated swizzle attrs, see python script below */ - {"xx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<= 0x03000000) + &Vector_AsMapping, /* PyMappingMethods *tp_as_mapping; */ +#else + NULL, +#endif /* More standard operations (here for binary compatibility) */ @@ -1802,8 +1915,8 @@ PyTypeObject vector_Type = { NULL, /* PyBufferProcs *tp_as_buffer; */ /*** Flags to define presence of optional/expanded features ***/ - Py_TPFLAGS_DEFAULT, - VectorObject_doc, /* char *tp_doc; Documentation string */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + NULL, /* char *tp_doc; Documentation string */ /*** Assigned meaning in release 2.0 ***/ /* call function for all accessible objects */ NULL, /* traverseproc tp_traverse; */ @@ -1855,10 +1968,13 @@ PyTypeObject vector_Type = { (i.e. it was allocated elsewhere by MEM_mallocN()) pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON (i.e. it must be created here with PyMEM_malloc())*/ -PyObject *newVectorObject(float *vec, int size, int type) +PyObject *newVectorObject(float *vec, int size, int type, PyTypeObject *base_type) { int i; - VectorObject *self = PyObject_NEW(VectorObject, &vector_Type); + VectorObject *self; + + if(base_type) self = base_type->tp_alloc(base_type, 0); + else self = PyObject_NEW(VectorObject, &vector_Type); if(size > 4 || size < 2) return NULL; @@ -1894,7 +2010,7 @@ PyObject *newVectorObject(float *vec, int size, int type) PyObject *newVectorObject_cb(PyObject *cb_user, int size, int cb_type, int cb_subtype) { float dummy[4] = {0.0, 0.0, 0.0, 0.0}; /* dummy init vector, callbacks will be used on access */ - VectorObject *self= (VectorObject *)newVectorObject(dummy, size, Py_NEW); + VectorObject *self= (VectorObject *)newVectorObject(dummy, size, Py_NEW, NULL); if(self) { Py_INCREF(cb_user); self->cb_user= cb_user; @@ -1941,7 +2057,7 @@ static PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat vecNew[z++] = (float)dot; dot = 0.0f; } - return newVectorObject(vecNew, vec_size, Py_NEW); + return newVectorObject(vecNew, vec_size, Py_NEW, NULL); } /*----------------------------Vector.negate() -------------------- diff --git a/source/blender/python/generic/vector.h b/source/blender/python/generic/vector.h index f519b2808cb..f6babac7ed9 100644 --- a/source/blender/python/generic/vector.h +++ b/source/blender/python/generic/vector.h @@ -34,8 +34,7 @@ #include "../intern/bpy_compat.h" extern PyTypeObject vector_Type; - -#define VectorObject_Check(v) (((PyObject *)v)->ob_type == &vector_Type) +#define VectorObject_Check(_v) PyObject_TypeCheck((_v), &vector_Type) typedef struct { /* keep aligned with BaseMathObject in Mathutils.h */ PyObject_VAR_HEAD @@ -50,7 +49,7 @@ typedef struct { /* keep aligned with BaseMathObject in Mathutils.h */ } VectorObject; /*prototypes*/ -PyObject *newVectorObject(float *vec, int size, int type); +PyObject *newVectorObject(float *vec, int size, int type, PyTypeObject *base_type); PyObject *newVectorObject_cb(PyObject *user, int size, int callback_type, int subtype); #endif /* EXPP_vector_h */ diff --git a/source/blender/python/intern/bpy_operator_wrap.c b/source/blender/python/intern/bpy_operator_wrap.c index b7e3c86dd91..60a9afda0c4 100644 --- a/source/blender/python/intern/bpy_operator_wrap.c +++ b/source/blender/python/intern/bpy_operator_wrap.c @@ -353,7 +353,8 @@ PyObject *PYOP_wrap_add(PyObject *self, PyObject *py_class) /* remove if it already exists */ if ((ot=WM_operatortype_find(idname))) { - Py_XDECREF((PyObject*)ot->pyop_data); + if(ot->pyop_data) + Py_XDECREF((PyObject*)ot->pyop_data); WM_operatortype_remove(idname); } diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 558722cc5e6..4729620bb8a 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -35,6 +35,7 @@ #include "RNA_define.h" /* for defining our own rna */ #include "MEM_guardedalloc.h" +#include "BKE_utildefines.h" #include "BKE_context.h" #include "BKE_global.h" /* evil G.* */ #include "BKE_report.h" @@ -204,13 +205,13 @@ static long pyrna_struct_hash( BPy_StructRNA * self ) /* use our own dealloc so we can free a property if we use one */ static void pyrna_struct_dealloc( BPy_StructRNA * self ) { - /* Note!! for some weired reason calling PyObject_DEL() directly crashes blender! */ if (self->freeptr && self->ptr.data) { IDP_FreeProperty(self->ptr.data); MEM_freeN(self->ptr.data); self->ptr.data= NULL; } + /* Note, for subclassed PyObjects we cant just call PyObject_DEL() directly or it will crash */ Py_TYPE(self)->tp_free(self); return; } @@ -820,108 +821,246 @@ static Py_ssize_t pyrna_prop_len( BPy_PropertyRNA * self ) return len; } -static PyObject *pyrna_prop_subscript( BPy_PropertyRNA * self, PyObject *key ) +/* internal use only */ +static PyObject *prop_subscript_collection_int(BPy_PropertyRNA * self, int keynum) { - PyObject *ret; PointerRNA newptr; - int keynum = 0; - char *keyname = NULL; - + + if(keynum < 0) keynum += RNA_property_collection_length(&self->ptr, self->prop); + + if(RNA_property_collection_lookup_int(&self->ptr, self->prop, keynum, &newptr)) + return pyrna_struct_CreatePyObject(&newptr); + + PyErr_SetString(PyExc_IndexError, "out of range"); + return NULL; +} +static PyObject *prop_subscript_array_int(BPy_PropertyRNA * self, int keynum) +{ + int len= RNA_property_array_length(self->prop); + + if(keynum < 0) keynum += len; + + if(keynum >= 0 && keynum < len) + return pyrna_prop_to_py_index(&self->ptr, self->prop, keynum); + + PyErr_SetString(PyExc_IndexError, "out of range"); + return NULL; +} + +static PyObject *prop_subscript_collection_str(BPy_PropertyRNA * self, char *keyname) +{ + PointerRNA newptr; + if(RNA_property_collection_lookup_string(&self->ptr, self->prop, keyname, &newptr)) + return pyrna_struct_CreatePyObject(&newptr); + + PyErr_SetString(PyExc_KeyError, "key not found"); + return NULL; +} +/* static PyObject *prop_subscript_array_str(BPy_PropertyRNA * self, char *keyname) */ + + + + +#if PY_VERSION_HEX >= 0x03000000 +static PyObject *prop_subscript_collection_slice(BPy_PropertyRNA * self, int start, int stop) +{ + PointerRNA newptr; + PyObject *list = PyList_New(stop - start); + int count; + + start = MIN2(start,stop); /* values are clamped from */ + + for(count = start; count < stop; count++) { + if(RNA_property_collection_lookup_int(&self->ptr, self->prop, count - start, &newptr)) { + PyList_SetItem(list, count - start, pyrna_struct_CreatePyObject(&newptr)); + } + else { + Py_DECREF(list); + + PyErr_SetString(PyExc_RuntimeError, "error getting an rna struct from a collection"); + return NULL; + } + } + + return list; +} +static PyObject *prop_subscript_array_slice(BPy_PropertyRNA * self, int start, int stop) +{ + PyObject *list = PyList_New(stop - start); + int count; + + start = MIN2(start,stop); /* values are clamped from PySlice_GetIndicesEx */ + + for(count = start; count < stop; count++) + PyList_SetItem(list, count - start, pyrna_prop_to_py_index(&self->ptr, self->prop, count)); + + return list; +} +#endif + +static PyObject *prop_subscript_collection(BPy_PropertyRNA * self, PyObject *key) +{ if (PyUnicode_Check(key)) { - keyname = _PyUnicode_AsString(key); - } else if (PyLong_Check(key)) { - keynum = PyLong_AsSsize_t(key); - } else { + return prop_subscript_collection_str(self, _PyUnicode_AsString(key)); + } + else if (PyLong_Check(key)) { + return prop_subscript_collection_int(self, PyLong_AsSsize_t(key)); + } +#if PY_VERSION_HEX >= 0x03000000 + else if (PySlice_Check(key)) { + int len= RNA_property_collection_length(&self->ptr, self->prop); + Py_ssize_t start, stop, step, slicelength; + + if (PySlice_GetIndicesEx((PySliceObject*)key, len, &start, &stop, &step, &slicelength) < 0) + return NULL; + + if (slicelength <= 0) { + return PyList_New(0); + } + else if (step == 1) { + return prop_subscript_collection_slice(self, start, stop); + } + else { + PyErr_SetString(PyExc_TypeError, "slice steps not supported with rna"); + return NULL; + } + } +#endif + else { PyErr_SetString(PyExc_AttributeError, "invalid key, key must be a string or an int"); return NULL; } - - if (RNA_property_type(self->prop) == PROP_COLLECTION) { - int ok; - if (keyname) ok = RNA_property_collection_lookup_string(&self->ptr, self->prop, keyname, &newptr); - else ok = RNA_property_collection_lookup_int(&self->ptr, self->prop, keynum, &newptr); - - if (ok) { - ret = pyrna_struct_CreatePyObject(&newptr); - } else { - PyErr_SetString(PyExc_AttributeError, "out of range"); - ret = NULL; - } - - } else if (keyname) { - PyErr_SetString(PyExc_AttributeError, "string keys are only supported for collections"); - ret = NULL; - } else { - int len = RNA_property_array_length(self->prop); - - if (len==0) { /* not an array*/ - PyErr_Format(PyExc_AttributeError, "not an array or collection %d", keynum); - ret = NULL; - } - - if (keynum >= len){ - PyErr_SetString(PyExc_AttributeError, "index out of range"); - ret = NULL; - } else { /* not an array*/ - ret = pyrna_prop_to_py_index(&self->ptr, self->prop, keynum); - } - } - - return ret; } - -static int pyrna_prop_assign_subscript( BPy_PropertyRNA * self, PyObject *key, PyObject *value ) +static PyObject *prop_subscript_array(BPy_PropertyRNA * self, PyObject *key) { - int ret = 0; - int keynum = 0; - char *keyname = NULL; + /*if (PyUnicode_Check(key)) { + return prop_subscript_array_str(self, _PyUnicode_AsString(key)); + } else*/ + if (PyLong_Check(key)) { + return prop_subscript_array_int(self, PyLong_AsSsize_t(key)); + } +#if PY_VERSION_HEX >= 0x03000000 + else if (PySlice_Check(key)) { + int len= RNA_property_array_length(self->prop); + Py_ssize_t start, stop, step, slicelength; + + if (PySlice_GetIndicesEx((PySliceObject*)key, len, &start, &stop, &step, &slicelength) < 0) + return NULL; + + if (slicelength <= 0) { + return PyList_New(0); + } + else if (step == 1) { + return prop_subscript_array_slice(self, start, stop); + } + else { + PyErr_SetString(PyExc_TypeError, "slice steps not supported with rna"); + return NULL; + } + } +#endif + else { + PyErr_SetString(PyExc_AttributeError, "invalid key, key must be an int"); + return NULL; + } +} + +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->prop)) { /* arrays are currently fixed length, zero length means its not an array */ + return prop_subscript_array(self, key); + } else { + PyErr_SetString(PyExc_TypeError, "rna type is not an array or a collection"); + return NULL; + } + +} + +#if PY_VERSION_HEX >= 0x03000000 +static int prop_subscript_ass_array_slice(BPy_PropertyRNA * self, int begin, int end, PyObject *value) +{ + int count; + + /* values are clamped from */ + begin = MIN2(begin,end); + + for(count = begin; count < end; count++) { + if(pyrna_py_to_prop_index(&self->ptr, self->prop, count - begin, value) == -1) { + /* TODO - this is wrong since some values have been assigned... will need to fix that */ + return -1; /* pyrna_struct_CreatePyObject should set the error */ + } + } + + return 0; +} +#endif + +static int prop_subscript_ass_array_int(BPy_PropertyRNA * self, int keynum, PyObject *value) +{ + + int len= RNA_property_array_length(self->prop); + + if(keynum < 0) keynum += len; + + if(keynum >= 0 && keynum < len) + return pyrna_py_to_prop_index(&self->ptr, self->prop, keynum, value); + + PyErr_SetString(PyExc_IndexError, "out of range"); + return -1; +} + +static int pyrna_prop_ass_subscript( BPy_PropertyRNA * self, PyObject *key, PyObject *value ) +{ + /* char *keyname = NULL; */ /* not supported yet */ if (!RNA_property_editable(&self->ptr, self->prop)) { PyErr_Format( PyExc_AttributeError, "PropertyRNA - attribute \"%s\" from \"%s\" is read-only", RNA_property_identifier(self->prop), RNA_struct_identifier(self->ptr.type) ); return -1; } - if (PyUnicode_Check(key)) { - keyname = _PyUnicode_AsString(key); - } else if (PyLong_Check(key)) { - keynum = PyLong_AsSsize_t(key); - } else { - PyErr_SetString(PyExc_AttributeError, "PropertyRNA - invalid key, key must be a string or an int"); + /* maybe one day we can support this... */ + if (RNA_property_type(self->prop) == PROP_COLLECTION) { + PyErr_Format( PyExc_AttributeError, "PropertyRNA - attribute \"%s\" from \"%s\" is a collection, assignment not supported", RNA_property_identifier(self->prop), RNA_struct_identifier(self->ptr.type) ); return -1; } - - if (RNA_property_type(self->prop) == PROP_COLLECTION) { - PyErr_SetString(PyExc_AttributeError, "PropertyRNA - assignment is not supported for collections (yet)"); - ret = -1; - } else if (keyname) { - PyErr_SetString(PyExc_AttributeError, "PropertyRNA - string keys are only supported for collections"); - ret = -1; - } else { - int len = RNA_property_array_length(self->prop); - - if (len==0) { /* not an array*/ - PyErr_Format(PyExc_AttributeError, "PropertyRNA - not an array or collection %d", keynum); - ret = -1; + + if (PyLong_Check(key)) { + return prop_subscript_ass_array_int(self, PyLong_AsSsize_t(key), value); + } +#if PY_VERSION_HEX >= 0x03000000 + else if (PySlice_Check(key)) { + int len= RNA_property_array_length(self->prop); + Py_ssize_t start, stop, step, slicelength; + + if (PySlice_GetIndicesEx((PySliceObject*)key, len, &start, &stop, &step, &slicelength) < 0) + return -1; + + if (slicelength <= 0) { + return 0; } - - if (keynum >= len){ - PyErr_SetString(PyExc_AttributeError, "PropertyRNA - index out of range"); - ret = -1; - } else { - ret = pyrna_py_to_prop_index(&self->ptr, self->prop, keynum, value); + else if (step == 1) { + return prop_subscript_ass_array_slice(self, start, stop, value); + } + else { + PyErr_SetString(PyExc_TypeError, "slice steps not supported with rna"); + return -1; } } - - return ret; +#endif + else { + PyErr_SetString(PyExc_AttributeError, "invalid key, key must be an int"); + return -1; + } } - static PyMappingMethods pyrna_prop_as_mapping = { ( lenfunc ) pyrna_prop_len, /* mp_length */ ( binaryfunc ) pyrna_prop_subscript, /* mp_subscript */ - ( objobjargproc ) pyrna_prop_assign_subscript, /* mp_ass_subscript */ + ( objobjargproc ) pyrna_prop_ass_subscript, /* mp_ass_subscript */ }; static int pyrna_prop_contains(BPy_PropertyRNA * self, PyObject *value) @@ -1130,7 +1269,7 @@ static int pyrna_struct_setattro( BPy_StructRNA * self, PyObject *pyname, PyObje return pyrna_py_to_prop(&self->ptr, prop, NULL, value); } -PyObject *pyrna_prop_keys(BPy_PropertyRNA *self) +static PyObject *pyrna_prop_keys(BPy_PropertyRNA *self) { PyObject *ret; if (RNA_property_type(self->prop) != PROP_COLLECTION) { @@ -1162,7 +1301,7 @@ PyObject *pyrna_prop_keys(BPy_PropertyRNA *self) return ret; } -PyObject *pyrna_prop_items(BPy_PropertyRNA *self) +static PyObject *pyrna_prop_items(BPy_PropertyRNA *self) { PyObject *ret; if (RNA_property_type(self->prop) != PROP_COLLECTION) { @@ -1203,7 +1342,7 @@ PyObject *pyrna_prop_items(BPy_PropertyRNA *self) } -PyObject *pyrna_prop_values(BPy_PropertyRNA *self) +static PyObject *pyrna_prop_values(BPy_PropertyRNA *self) { PyObject *ret; @@ -1225,6 +1364,243 @@ PyObject *pyrna_prop_values(BPy_PropertyRNA *self) return ret; } +#if (PY_VERSION_HEX >= 0x03000000) /* foreach needs py3 */ +static void foreach_attr_type( BPy_PropertyRNA *self, char *attr, + /* values to assign */ + RawPropertyType *raw_type, int *attr_tot, int *attr_signed ) +{ + PropertyRNA *prop; + *raw_type= -1; + *attr_tot= 0; + *attr_signed= 0; + + RNA_PROP_BEGIN(&self->ptr, itemptr, self->prop) { + prop = RNA_struct_find_property(&itemptr, attr); + *raw_type= RNA_property_raw_type(prop); + *attr_tot = RNA_property_array_length(prop); + *attr_signed= (RNA_property_subtype(prop)==PROP_UNSIGNED) ? 0:1; + break; + } + RNA_PROP_END; +} + +/* pyrna_prop_foreach_get/set both use this */ +static int foreach_parse_args( + BPy_PropertyRNA *self, PyObject *args, + + /*values to assign */ + char **attr, PyObject **seq, int *tot, int *size, RawPropertyType *raw_type, int *attr_tot, int *attr_signed) +{ +#if 0 + int array_tot; + int target_tot; +#endif + + *size= *raw_type= *attr_tot= *attr_signed= 0; + + if(!PyArg_ParseTuple(args, "sO", attr, seq) || (!PySequence_Check(*seq) && PyObject_CheckBuffer(*seq))) { + PyErr_SetString( PyExc_TypeError, "foreach_get(attr, sequence) expects a string and a sequence" ); + return -1; + } + + *tot= PySequence_Length(*seq); // TODO - buffer may not be a sequence! array.array() is tho. + + if(*tot>0) { + foreach_attr_type(self, *attr, raw_type, attr_tot, attr_signed); + *size= RNA_raw_type_sizeof(*raw_type); + +#if 0 // works fine but not strictly needed, we could allow RNA_property_collection_raw_* to do the checks + if((*attr_tot) < 1) + *attr_tot= 1; + + if (RNA_property_type(self->prop) == PROP_COLLECTION) + array_tot = RNA_property_collection_length(&self->ptr, self->prop); + else + array_tot = RNA_property_array_length(self->prop); + + + target_tot= array_tot * (*attr_tot); + + /* rna_access.c - rna_raw_access(...) uses this same method */ + if(target_tot != (*tot)) { + PyErr_Format( PyExc_TypeError, "foreach_get(attr, sequence) sequence length mismatch given %d, needed %d", *tot, target_tot); + return -1; + } +#endif + } + + return 0; +} + +static int foreach_compat_buffer(RawPropertyType raw_type, int attr_signed, const char *format) +{ + char f = format ? *format:'B'; /* B is assumed when not set */ + + switch(raw_type) { + case PROP_RAW_CHAR: + if (attr_signed) return (f=='b') ? 1:0; + else return (f=='B') ? 1:0; + case PROP_RAW_SHORT: + if (attr_signed) return (f=='h') ? 1:0; + else return (f=='H') ? 1:0; + case PROP_RAW_INT: + if (attr_signed) return (f=='i') ? 1:0; + else return (f=='I') ? 1:0; + case PROP_RAW_FLOAT: + return (f=='f') ? 1:0; + case PROP_RAW_DOUBLE: + return (f=='d') ? 1:0; + } + + return 0; +} + +static PyObject *foreach_getset(BPy_PropertyRNA *self, PyObject *args, int set) +{ + PyObject *item; + int i=0, ok, buffer_is_compat; + void *array= NULL; + + /* get/set both take the same args currently */ + char *attr; + PyObject *seq; + int tot, size, attr_tot, attr_signed; + RawPropertyType raw_type; + + if(foreach_parse_args(self, args, &attr, &seq, &tot, &size, &raw_type, &attr_tot, &attr_signed) < 0) + return NULL; + + if(tot==0) + Py_RETURN_NONE; + + + + if(set) { /* get the array from python */ + buffer_is_compat = 0; + if(PyObject_CheckBuffer(seq)) { + Py_buffer buf; + PyObject_GetBuffer(seq, &buf, PyBUF_SIMPLE | PyBUF_FORMAT); + + /* check if the buffer matches */ + + buffer_is_compat = foreach_compat_buffer(raw_type, attr_signed, buf.format); + + if(buffer_is_compat) { + ok = RNA_property_collection_raw_set(NULL, &self->ptr, self->prop, attr, buf.buf, raw_type, tot); + } + + PyBuffer_Release(&buf); + } + + /* could not use the buffer, fallback to sequence */ + if(!buffer_is_compat) { + array= PyMem_Malloc(size * tot); + + for( ; iptr, self->prop, attr, array, raw_type, tot); + } + } + else { + buffer_is_compat = 0; + if(PyObject_CheckBuffer(seq)) { + Py_buffer buf; + PyObject_GetBuffer(seq, &buf, PyBUF_SIMPLE | PyBUF_FORMAT); + + /* check if the buffer matches, TODO - signed/unsigned types */ + + buffer_is_compat = foreach_compat_buffer(raw_type, attr_signed, buf.format); + + if(buffer_is_compat) { + ok = RNA_property_collection_raw_get(NULL, &self->ptr, self->prop, attr, buf.buf, raw_type, tot); + } + + PyBuffer_Release(&buf); + } + + /* could not use the buffer, fallback to sequence */ + if(!buffer_is_compat) { + array= PyMem_Malloc(size * tot); + + ok = RNA_property_collection_raw_get(NULL, &self->ptr, self->prop, attr, array, raw_type, tot); + + if(!ok) i= tot; /* skip the loop */ + + for( ; i= 0x03000000) */ + /* A bit of a kludge, make a list out of a collection or array, * then return the lists iter function, not especially fast but convenient for now */ PyObject *pyrna_prop_iter(BPy_PropertyRNA *self) @@ -1259,14 +1635,20 @@ PyObject *pyrna_prop_iter(BPy_PropertyRNA *self) } static struct PyMethodDef pyrna_struct_methods[] = { - {"__dir__", (PyCFunction)pyrna_struct_dir, METH_NOARGS, ""}, + {"__dir__", (PyCFunction)pyrna_struct_dir, METH_NOARGS, NULL}, {NULL, NULL, 0, NULL} }; static struct PyMethodDef pyrna_prop_methods[] = { - {"keys", (PyCFunction)pyrna_prop_keys, METH_NOARGS, ""}, - {"items", (PyCFunction)pyrna_prop_items, METH_NOARGS, ""}, - {"values", (PyCFunction)pyrna_prop_values, METH_NOARGS, ""}, + {"keys", (PyCFunction)pyrna_prop_keys, METH_NOARGS, NULL}, + {"items", (PyCFunction)pyrna_prop_items, METH_NOARGS,NULL}, + {"values", (PyCFunction)pyrna_prop_values, METH_NOARGS, NULL}, + +#if (PY_VERSION_HEX >= 0x03000000) + /* array accessor function */ + {"foreach_get", (PyCFunction)pyrna_prop_foreach_get, METH_VARARGS, NULL}, + {"foreach_set", (PyCFunction)pyrna_prop_foreach_set, METH_VARARGS, NULL}, +#endif {NULL, NULL, 0, NULL} }; diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 92b71e9fff0..ffeb342df77 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -79,7 +79,7 @@ void WM_keymap_tweak (ListBase *lb, short type, short val, int modifier, short ListBase *WM_keymap_listbase (struct wmWindowManager *wm, const char *nameid, int spaceid, int regionid); -char *WM_key_event_string(short type); +const char *WM_key_event_string(short type); char *WM_key_event_operator_string(const struct bContext *C, const char *opname, int opcontext, struct IDProperty *properties, char *str, int len); /* handlers */ diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 9b987cdfa51..e3a7a906fef 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -128,6 +128,7 @@ typedef struct wmNotifier { #define NC_BRUSH (11<<24) #define NC_TEXT (12<<24) #define NC_WORLD (13<<24) +#define NC_FILE (14<<24) /* data type, 256 entries is enough, it can overlap */ #define NOTE_DATA 0x00FF0000 @@ -182,6 +183,10 @@ typedef struct wmNotifier { /* NC_TEXT Text */ #define ND_CURSOR (50<<16) #define ND_DISPLAY (51<<16) + + /* NC_FILE Filebrowser */ +#define ND_PARAMS (60<<16) +#define ND_FILELIST (61<<16) /* subtype, 256 entries too */ #define NOTE_SUBTYPE 0x0000FF00 diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 286d1216f66..e520067b9e5 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -733,17 +733,20 @@ static int wm_handler_ui_call(bContext *C, wmEventHandler *handler, wmEvent *eve ScrArea *area= CTX_wm_area(C); ARegion *region= CTX_wm_region(C); ARegion *menu= CTX_wm_menu(C); - int retval; + int retval, always_pass; /* we set context to where ui handler came from */ if(handler->ui_area) CTX_wm_area_set(C, handler->ui_area); if(handler->ui_region) CTX_wm_region_set(C, handler->ui_region); if(handler->ui_menu) CTX_wm_menu_set(C, handler->ui_menu); + /* in advance to avoid access to freed event on window close */ + always_pass= wm_event_always_pass(event); + retval= handler->ui_handle(C, event, handler->ui_userdata); /* putting back screen context */ - if((retval != WM_UI_HANDLER_BREAK) || wm_event_always_pass(event)) { + if((retval != WM_UI_HANDLER_BREAK) || always_pass) { CTX_wm_area_set(C, area); CTX_wm_region_set(C, region); CTX_wm_menu_set(C, menu); @@ -776,7 +779,7 @@ static int wm_handler_fileselect_call(bContext *C, ListBase *handlers, wmEventHa case EVT_FILESELECT_OPEN: case EVT_FILESELECT_FULL_OPEN: { - short flag =0; short display =FILE_SHORTDISPLAY; short filter =0; short sort =FILE_SORTALPHA; + short flag =0; short display =FILE_SHORTDISPLAY; short filter =0; short sort =FILE_SORT_ALPHA; char *path= RNA_string_get_alloc(handler->op->ptr, "filename", NULL, 0); if(event->val==EVT_FILESELECT_OPEN) @@ -872,6 +875,7 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) { wmEventHandler *handler, *nexthandler; int action= WM_HANDLER_CONTINUE; + int always_pass; if(handlers==NULL) return action; @@ -881,6 +885,8 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) /* optional boundbox */ if(handler_boundbox_test(handler, event)) { + /* in advance to avoid access to freed event on window close */ + always_pass= wm_event_always_pass(event); /* modal+blocking handler */ if(handler->flag & WM_HANDLER_BLOCKING) @@ -912,7 +918,7 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) action= wm_handler_operator_call(C, handlers, handler, event, NULL); } - if(!wm_event_always_pass(event) && action==WM_HANDLER_BREAK) + if(!always_pass && action==WM_HANDLER_BREAK) break; } diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 861080f30ba..29ec58befd9 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -575,7 +575,7 @@ void WM_write_file(bContext *C, char *target, ReportList *reports) // } if (G.fileflags & G_AUTOPACK) { - packAll(); + packAll(G.main, reports); } ED_object_exit_editmode(C, 0); diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index 85028e3ea1a..b914e63788d 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -154,7 +154,7 @@ ListBase *WM_keymap_listbase(wmWindowManager *wm, const char *nameid, int spacei /* ***************** get string from key events **************** */ -char *WM_key_event_string(short type) +const char *WM_key_event_string(short type) { const char *name= NULL; if(RNA_enum_name(event_type_items, (int)type, &name)) diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 410cd11f1bf..7f9a2153dc3 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -418,7 +418,7 @@ static uiBlock *wm_block_search_menu(bContext *C, ARegion *ar, void *arg_op) uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_RET_1); but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 10, 180, 19, ""); - uiButSetSearchFunc(but, operator_search_cb, NULL, operator_call_cb); + uiButSetSearchFunc(but, operator_search_cb, NULL, operator_call_cb, NULL); /* fake button, it holds space for search items */ uiDefBut(block, LABEL, 0, "", 10, 10 - uiSearchBoxhHeight(), 180, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL); diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index ade5a2a64a8..cd0d551211f 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -151,7 +151,7 @@ IF(WIN32) COMMAND xcopy /E /Y \"${WIN_SOURCE_DIR}\\release\\ui\\*.*\" \"${TARGETDIR}\\.blender\\ui\" COMMAND xcopy /E /Y \"${WIN_SOURCE_DIR}\\release\\plugins\\*.*\" \"${TARGETDIR}\\plugins\" COMMAND copy /Y \"${WIN_SOURCE_DIR}\\release\\text\\*.*\" \"${TARGETDIR}\" - COMMAND copy /Y \"${WIN_SOURCE_DIR}\\release\\windows\\extra\\python25.zip\" \"${TARGETDIR}\\\" + COMMAND copy /Y \"${WIN_SOURCE_DIR}\\release\\windows\\extra\\python26.zip\" \"${TARGETDIR}\\\" ) FILE(TO_NATIVE_PATH "${LIBDIR}" WIN_LIBDIR) @@ -164,7 +164,8 @@ IF(WIN32) COMMAND copy /Y \"${WIN_LIBDIR}\\sdl\\lib\\SDL.dll\" \"${TARGETDIR}\\\" COMMAND copy /Y \"${WIN_LIBDIR}\\zlib\\lib\\zlib.dll\" \"${TARGETDIR}\\\" COMMAND copy /Y \"${WIN_LIBDIR}\\tiff\\lib\\libtiff.dll\" \"${TARGETDIR}\\\" - COMMAND copy /Y \"${WIN_LIBDIR}\\python\\lib\\python25.dll\" \"${TARGETDIR}\\\" + COMMAND copy /Y \"${WIN_LIBDIR}\\python\\lib\\python26.dll\" \"${TARGETDIR}\\\" + COMMAND copy /Y \"${WIN_LIBDIR}\\python\\lib\\python26_d.dll\" \"${TARGETDIR}\\\" COMMAND copy /Y \"${WIN_LIBDIR}\\pthreads\\lib\\pthreadVC2.dll\" \"${TARGETDIR}\\\" ) diff --git a/source/gameengine/BlenderRoutines/Makefile b/source/gameengine/BlenderRoutines/Makefile index 549e466c4e0..ffa99a0c1b2 100644 --- a/source/gameengine/BlenderRoutines/Makefile +++ b/source/gameengine/BlenderRoutines/Makefile @@ -54,6 +54,7 @@ CPPFLAGS += -I../../blender/render/extern/include CPPFLAGS += -I../../blender/blenloader CPPFLAGS += -I../../blender/blenfont CPPFLAGS += -I../../blender/gpu +CPPFLAGS += -I../../blender/makesrna CPPFLAGS += -I../Converter CPPFLAGS += -I../Expressions CPPFLAGS += -I../GameLogic diff --git a/source/gameengine/Converter/BL_ActionActuator.cpp b/source/gameengine/Converter/BL_ActionActuator.cpp index ce4311f57bf..bed99a4f502 100644 --- a/source/gameengine/Converter/BL_ActionActuator.cpp +++ b/source/gameengine/Converter/BL_ActionActuator.cpp @@ -446,7 +446,7 @@ PyObject* BL_ActionActuator::PyGetAction(PyObject* args, ShowDeprecationWarning("getAction()", "the action property"); if (m_action){ - return PyString_FromString(m_action->id.name+2); + return PyUnicode_FromString(m_action->id.name+2); } Py_RETURN_NONE; } @@ -796,7 +796,7 @@ PyObject* BL_ActionActuator::PySetFrameProperty(PyObject* args, } PyObject* BL_ActionActuator::PyGetChannel(PyObject* value) { - char *string= PyString_AsString(value); + char *string= _PyUnicode_AsString(value); if (!string) { PyErr_SetString(PyExc_TypeError, "expected a single string"); @@ -888,7 +888,7 @@ PyObject* BL_ActionActuator::PySetType(PyObject* args, PyObject* BL_ActionActuator::PyGetContinue() { ShowDeprecationWarning("getContinue()", "the continue property"); - return PyInt_FromLong((long)(m_end_reset==0)); + return PyLong_FromSsize_t((long)(m_end_reset==0)); } PyObject* BL_ActionActuator::PySetContinue(PyObject* value) { @@ -1005,19 +1005,15 @@ PyTypeObject BL_ActionActuator::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject BL_ActionActuator::Parents[] = { - &BL_ActionActuator::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IActuator::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef BL_ActionActuator::Methods[] = { @@ -1065,37 +1061,24 @@ PyAttributeDef BL_ActionActuator::Attributes[] = { { NULL } //Sentinel }; -PyObject* BL_ActionActuator::py_getattro(PyObject *attr) { - py_getattro_up(SCA_IActuator); -} - -PyObject* BL_ActionActuator::py_getattro_dict() { - py_getattro_dict_up(SCA_IActuator); -} - -int BL_ActionActuator::py_setattro(PyObject *attr, PyObject* value) { - py_setattro_up(SCA_IActuator); -} - - PyObject* BL_ActionActuator::pyattr_get_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { BL_ActionActuator* self= static_cast(self_v); - return PyString_FromString(self->GetAction() ? self->GetAction()->id.name+2 : ""); + return PyUnicode_FromString(self->GetAction() ? self->GetAction()->id.name+2 : ""); } int BL_ActionActuator::pyattr_set_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { BL_ActionActuator* self= static_cast(self_v); - if (!PyString_Check(value)) + if (!PyUnicode_Check(value)) { PyErr_SetString(PyExc_ValueError, "actuator.action = val: Action Actuator, expected the string name of the action"); return PY_SET_ATTR_FAIL; } bAction *action= NULL; - STR_String val = PyString_AsString(value); + STR_String val = _PyUnicode_AsString(value); if (val != "") { diff --git a/source/gameengine/Converter/BL_ActionActuator.h b/source/gameengine/Converter/BL_ActionActuator.h index 422b16bb3ec..e328ce126ca 100644 --- a/source/gameengine/Converter/BL_ActionActuator.h +++ b/source/gameengine/Converter/BL_ActionActuator.h @@ -49,9 +49,8 @@ public: short blendin, short priority, short end_reset, - float stride, - PyTypeObject* T=&Type) - : SCA_IActuator(gameobj,T), + float stride) + : SCA_IActuator(gameobj), m_lastpos(0, 0, 0), m_blendframe(0), @@ -113,10 +112,6 @@ public: KX_PYMETHOD_DOC(BL_ActionActuator,setChannel); - virtual PyObject* py_getattro(PyObject* attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject* attr, PyObject* value); - static PyObject* pyattr_get_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.cpp b/source/gameengine/Converter/BL_ShapeActionActuator.cpp index 7aa8714de3a..970539777f4 100644 --- a/source/gameengine/Converter/BL_ShapeActionActuator.cpp +++ b/source/gameengine/Converter/BL_ShapeActionActuator.cpp @@ -427,20 +427,17 @@ PyTypeObject BL_ShapeActionActuator::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, + &SCA_IActuator::Type, + 0,0,0,0,0,0, + py_base_new }; -PyParentObject BL_ShapeActionActuator::Parents[] = { - &BL_ShapeActionActuator::Type, - &SCA_IActuator::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL -}; PyMethodDef BL_ShapeActionActuator::Methods[] = { {"setAction", (PyCFunction) BL_ShapeActionActuator::sPySetAction, METH_VARARGS, (PY_METHODCHAR)SetAction_doc}, @@ -480,19 +477,6 @@ PyAttributeDef BL_ShapeActionActuator::Attributes[] = { { NULL } //Sentinel }; - -PyObject* BL_ShapeActionActuator::py_getattro(PyObject* attr) { - py_getattro_up(SCA_IActuator); -} - -PyObject* BL_ShapeActionActuator::py_getattro_dict() { - py_getattro_dict_up(SCA_IActuator); -} - -int BL_ShapeActionActuator::py_setattro(PyObject *attr, PyObject* value) { - py_setattro_up(SCA_IActuator); -} - /* setStart */ const char BL_ShapeActionActuator::GetAction_doc[] = "getAction()\n" @@ -501,7 +485,7 @@ const char BL_ShapeActionActuator::GetAction_doc[] = PyObject* BL_ShapeActionActuator::PyGetAction() { ShowDeprecationWarning("getAction()", "the action property"); if (m_action){ - return PyString_FromString(m_action->id.name+2); + return PyUnicode_FromString(m_action->id.name+2); } Py_RETURN_NONE; } @@ -860,21 +844,21 @@ PyObject* BL_ShapeActionActuator::PySetType(PyObject* args) { PyObject* BL_ShapeActionActuator::pyattr_get_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { BL_ShapeActionActuator* self= static_cast(self_v); - return PyString_FromString(self->GetAction() ? self->GetAction()->id.name+2 : ""); + return PyUnicode_FromString(self->GetAction() ? self->GetAction()->id.name+2 : ""); } int BL_ShapeActionActuator::pyattr_set_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { BL_ShapeActionActuator* self= static_cast(self_v); /* exact copy of BL_ActionActuator's function from here down */ - if (!PyString_Check(value)) + if (!PyUnicode_Check(value)) { PyErr_SetString(PyExc_ValueError, "actuator.action = val: Shape Action Actuator, expected the string name of the action"); return PY_SET_ATTR_FAIL; } bAction *action= NULL; - STR_String val = PyString_AsString(value); + STR_String val = _PyUnicode_AsString(value); if (val != "") { diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.h b/source/gameengine/Converter/BL_ShapeActionActuator.h index d268eef6d23..890fe3f9de9 100644 --- a/source/gameengine/Converter/BL_ShapeActionActuator.h +++ b/source/gameengine/Converter/BL_ShapeActionActuator.h @@ -50,9 +50,8 @@ public: short playtype, short blendin, short priority, - float stride, - PyTypeObject* T=&Type) - : SCA_IActuator(gameobj,T), + float stride) + : SCA_IActuator(gameobj), m_lastpos(0, 0, 0), m_blendframe(0), @@ -106,10 +105,6 @@ public: KX_PYMETHOD_DOC_NOARGS(BL_ShapeActionActuator,GetType); KX_PYMETHOD_DOC_VARARGS(BL_ShapeActionActuator,SetType); - virtual PyObject* py_getattro(PyObject* attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject* attr, PyObject* value); - static PyObject* pyattr_get_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); diff --git a/source/gameengine/Expressions/BoolValue.cpp b/source/gameengine/Expressions/BoolValue.cpp index d90da8b3a92..6779c2ea780 100644 --- a/source/gameengine/Expressions/BoolValue.cpp +++ b/source/gameengine/Expressions/BoolValue.cpp @@ -29,7 +29,6 @@ const STR_String CBoolValue::sTrueString = "TRUE"; const STR_String CBoolValue::sFalseString = "FALSE"; - CBoolValue::CBoolValue() /* pre: false @@ -210,5 +209,5 @@ CValue* CBoolValue::GetReplica() PyObject* CBoolValue::ConvertValueToPython() { - return PyInt_FromLong(m_bool != 0); + return PyBool_FromLong(m_bool != 0); } diff --git a/source/gameengine/Expressions/IntValue.cpp b/source/gameengine/Expressions/IntValue.cpp index 227518e9439..b782de4bef6 100644 --- a/source/gameengine/Expressions/IntValue.cpp +++ b/source/gameengine/Expressions/IntValue.cpp @@ -330,7 +330,7 @@ void CIntValue::SetValue(CValue* newval) PyObject* CIntValue::ConvertValueToPython() { if((m_int > INT_MIN) && (m_int < INT_MAX)) - return PyInt_FromLong(m_int); + return PyLong_FromSsize_t(m_int); else return PyLong_FromLongLong(m_int); } diff --git a/source/gameengine/Expressions/ListValue.cpp b/source/gameengine/Expressions/ListValue.cpp index 59344ddb7b7..38b00dcc8fb 100644 --- a/source/gameengine/Expressions/ListValue.cpp +++ b/source/gameengine/Expressions/ListValue.cpp @@ -76,9 +76,9 @@ PyObject* listvalue_mapping_subscript(PyObject* self, PyObject* pyindex) return NULL; } - if (PyString_Check(pyindex)) + if (PyUnicode_Check(pyindex)) { - CValue *item = ((CListValue*) list)->FindValue(PyString_AsString(pyindex)); + CValue *item = ((CListValue*) list)->FindValue(_PyUnicode_AsString(pyindex)); if (item) { PyObject* pyobj = item->ConvertValueToPython(); if(pyobj) @@ -87,14 +87,14 @@ PyObject* listvalue_mapping_subscript(PyObject* self, PyObject* pyindex) return item->GetProxy(); } } - else if (PyInt_Check(pyindex)) + else if (PyLong_Check(pyindex)) { - int index = PyInt_AsLong(pyindex); + int index = PyLong_AsSsize_t(pyindex); return listvalue_buffer_item(self, index); /* wont add a ref */ } PyObject *pyindex_str = PyObject_Repr(pyindex); /* new ref */ - PyErr_Format(PyExc_KeyError, "CList[key]: '%s' key not in list", PyString_AsString(pyindex_str)); + PyErr_Format(PyExc_KeyError, "CList[key]: '%s' key not in list", _PyUnicode_AsString(pyindex_str)); Py_DECREF(pyindex_str); return NULL; } @@ -220,12 +220,12 @@ static int listvalue_buffer_contains(PyObject *self_v, PyObject *value) return -1; } - if (PyString_Check(value)) { - if (self->FindValue((const char *)PyString_AsString(value))) { + if (PyUnicode_Check(value)) { + if (self->FindValue((const char *)_PyUnicode_AsString(value))) { return 1; } } - else if (BGE_PROXY_CHECK_TYPE(value)) { /* not dict like at all but this worked before __contains__ was used */ + else if (PyObject_TypeCheck(value, &CValue::Type)) { /* not dict like at all but this worked before __contains__ was used */ CValue *item= static_cast(BGE_PROXY_REF(value)); for (int i=0; i < self->GetCount(); i++) if (self->GetValue(i) == item) // Com @@ -289,25 +289,19 @@ PyTypeObject CListValue::Type = { 0, /*tp_hash*/ 0, /*tp_call */ 0, - py_base_getattro, - py_base_setattro, + NULL, + NULL, 0, - Py_TPFLAGS_DEFAULT, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, 0,0,0,0,0,0,0, - Methods -}; - - - -PyParentObject CListValue::Parents[] = { - &CListValue::Type, + Methods, + 0, + 0, &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; - - - PyMethodDef CListValue::Methods[] = { /* List style access */ {"append", (PyCFunction)CListValue::sPyappend,METH_O}, @@ -329,21 +323,12 @@ PyAttributeDef CListValue::Attributes[] = { { NULL } //Sentinel }; -PyObject* CListValue::py_getattro(PyObject* attr) { - py_getattro_up(CValue); -} - -PyObject* CListValue::py_getattro_dict() { - py_getattro_dict_up(CValue); -} - - ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// -CListValue::CListValue(PyTypeObject *T ) -: CPropValue(T) +CListValue::CListValue() +: CPropValue() { m_bReleaseContents=true; } @@ -559,7 +544,7 @@ PyObject* CListValue::Pyindex(PyObject *value) CValue* elem = GetValue(i); if (checkobj==elem || CheckEqual(checkobj,elem)) { - result = PyInt_FromLong(i); + result = PyLong_FromSsize_t(i); break; } } @@ -582,7 +567,7 @@ PyObject* CListValue::Pycount(PyObject* value) if (checkobj==NULL) { /* in this case just return that there are no items in the list */ PyErr_Clear(); - return PyInt_FromLong(0); + return PyLong_FromSsize_t(0); } int numelem = GetCount(); @@ -596,7 +581,7 @@ PyObject* CListValue::Pycount(PyObject* value) } checkobj->Release(); - return PyInt_FromLong(numfound); + return PyLong_FromSsize_t(numfound); } /* Matches python dict.get(key, [default]) */ @@ -623,7 +608,7 @@ PyObject* CListValue::Pyget(PyObject *args) /* Matches python dict.has_key() */ PyObject* CListValue::Pyhas_key(PyObject* value) { - if (PyString_Check(value) && FindValue((const char *)PyString_AsString(value))) + if (PyUnicode_Check(value) && FindValue((const char *)_PyUnicode_AsString(value))) Py_RETURN_TRUE; Py_RETURN_FALSE; diff --git a/source/gameengine/Expressions/ListValue.h b/source/gameengine/Expressions/ListValue.h index 68e900e25e0..98e6f216f11 100644 --- a/source/gameengine/Expressions/ListValue.h +++ b/source/gameengine/Expressions/ListValue.h @@ -24,7 +24,7 @@ class CListValue : public CPropValue //PLUGIN_DECLARE_SERIAL (CListValue,CValue) public: - CListValue(PyTypeObject *T = &Type); + CListValue(); virtual ~CListValue(); void AddConfigurationData(CValue* menuvalue); @@ -60,8 +60,6 @@ public: bool CheckEqual(CValue* first,CValue* second); - virtual PyObject* py_getattro(PyObject* attr); - virtual PyObject* py_getattro_dict(); virtual PyObject* py_repr(void) { PyObject *py_proxy= this->GetProxy(); PyObject *py_list= PySequence_List(py_proxy); diff --git a/source/gameengine/Expressions/PyObjectPlus.cpp b/source/gameengine/Expressions/PyObjectPlus.cpp index 2d4cc612aef..729fff31052 100644 --- a/source/gameengine/Expressions/PyObjectPlus.cpp +++ b/source/gameengine/Expressions/PyObjectPlus.cpp @@ -74,11 +74,13 @@ PyTypeObject PyObjectPlus::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, + NULL // no subtype }; @@ -91,106 +93,9 @@ PyObjectPlus::~PyObjectPlus() // assert(ob_refcnt==0); } -void PyObjectPlus::py_base_dealloc(PyObject *self) // python wrapper -{ - PyObjectPlus *self_plus= BGE_PROXY_REF(self); - if(self_plus) { - if(BGE_PROXY_PYOWNS(self)) { /* Does python own this?, then delete it */ - self_plus->m_proxy = NULL; /* Need this to stop ~PyObjectPlus from decrefing m_proxy otherwise its decref'd twice and py-debug crashes */ - delete self_plus; - } - - BGE_PROXY_REF(self)= NULL; // not really needed - } - PyObject_DEL( self ); -}; - -PyObjectPlus::PyObjectPlus(PyTypeObject *T) : SG_QList() // constructor -{ - MT_assert(T != NULL); - m_proxy= NULL; -}; - -/*------------------------------ - * PyObjectPlus Methods -- Every class, even the abstract one should have a Methods -------------------------------*/ -PyMethodDef PyObjectPlus::Methods[] = { - {"isA", (PyCFunction) sPyisA, METH_O}, - {NULL, NULL} /* Sentinel */ -}; - -PyAttributeDef PyObjectPlus::Attributes[] = { - KX_PYATTRIBUTE_RO_FUNCTION("invalid", PyObjectPlus, pyattr_get_invalid), - {NULL} //Sentinel -}; - -PyObject* PyObjectPlus::pyattr_get_invalid(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) -{ - Py_RETURN_FALSE; -} - -/*------------------------------ - * PyObjectPlus Parents -- Every class, even the abstract one should have parents -------------------------------*/ -PyParentObject PyObjectPlus::Parents[] = {&PyObjectPlus::Type, NULL}; - -/*------------------------------ - * PyObjectPlus attributes -- attributes -------------------------------*/ - - -/* This should be the entry in Type since it takes the C++ class from PyObjectPlus_Proxy */ -PyObject *PyObjectPlus::py_base_getattro(PyObject * self, PyObject *attr) -{ - PyObjectPlus *self_plus= BGE_PROXY_REF(self); - if(self_plus==NULL) { - if(!strcmp("invalid", PyString_AsString(attr))) { - Py_RETURN_TRUE; - } - PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG); - return NULL; - } - - PyObject *ret= self_plus->py_getattro(attr); - - /* Attribute not found, was this a __dict__ lookup?, otherwise set an error if none is set */ - if(ret==NULL) { - char *attr_str= PyString_AsString(attr); - - if (strcmp(attr_str, "__dict__")==0) - { - /* the error string will probably not - * be set but just incase clear it */ - PyErr_Clear(); - ret= self_plus->py_getattro_dict(); - } - else if (!PyErr_Occurred()) { - /* We looked for an attribute but it wasnt found - * since py_getattro didnt set the error, set it here */ - PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '%s'", self->ob_type->tp_name, attr_str); - } - } - return ret; -} - -/* This should be the entry in Type since it takes the C++ class from PyObjectPlus_Proxy */ -int PyObjectPlus::py_base_setattro(PyObject *self, PyObject *attr, PyObject *value) -{ - PyObjectPlus *self_plus= BGE_PROXY_REF(self); - if(self_plus==NULL) { - PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG); - return -1; - } - - if (value==NULL) - return self_plus->py_delattro(attr); - - return self_plus->py_setattro(attr, value); -} PyObject *PyObjectPlus::py_base_repr(PyObject *self) // This should be the entry in Type. { - PyObjectPlus *self_plus= BGE_PROXY_REF(self); if(self_plus==NULL) { PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG); @@ -200,42 +105,134 @@ PyObject *PyObjectPlus::py_base_repr(PyObject *self) // This should be the ent return self_plus->py_repr(); } -PyObject *PyObjectPlus::py_getattro(PyObject* attr) + +PyObject * PyObjectPlus::py_base_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { - PyObject *descr = PyDict_GetItem(Type.tp_dict, attr); \ - if (descr == NULL) { - return NULL; /* py_base_getattro sets the error, this way we can avoid setting the error at many levels */ - } else { - /* Copied from py_getattro_up */ - if (PyCObject_Check(descr)) { - return py_get_attrdef((void *)this, (const PyAttributeDef*)PyCObject_AsVoidPtr(descr)); - } else if (descr->ob_type->tp_descr_get) { - return PyCFunction_New(((PyMethodDescrObject *)descr)->d_method, this->m_proxy); - } else { - return NULL; - } - /* end py_getattro_up copy */ + PyTypeObject *base_type; + PyObjectPlus_Proxy *base = NULL; + + if (!PyArg_ParseTuple(args, "O:Base PyObjectPlus", &base)) + return NULL; + + /* the 'base' PyObject may be subclassed (multiple times even) + * we need to find the first C++ defined class to check 'type' + * is a subclass of the base arguments type. + * + * This way we can share one tp_new function for every PyObjectPlus + * + * eg. + * + * # CustomOb is called 'type' in this C code + * class CustomOb(GameTypes.KX_GameObject): + * pass + * + * # this calls py_base_new(...), the type of 'CustomOb' is checked to be a subclass of the 'cont.owner' type + * ob = CustomOb(cont.owner) + * + * */ + base_type= Py_TYPE(base); + while(base_type && !BGE_PROXY_CHECK_TYPE(base_type)) + base_type= base_type->tp_base; + + if(base_type==NULL || !BGE_PROXY_CHECK_TYPE(base_type)) { + PyErr_SetString(PyExc_TypeError, "can't subclass from a blender game type because the argument given is not a game class or subclass"); + return NULL; } + + /* use base_type rather then Py_TYPE(base) because we could alredy be subtyped */ + if(!PyType_IsSubtype(type, base_type)) { + PyErr_Format(PyExc_TypeError, "can't subclass blender game type <%s> from <%s> because it is not a subclass", base_type->tp_name, type->tp_name); + return NULL; + } + + /* invalidate the existing base and return a new subclassed one, + * this is a bit dodgy in that it also attaches its self to the existing object + * which is not really 'correct' python OO but for our use its OK. */ + + PyObjectPlus_Proxy *ret = (PyObjectPlus_Proxy *) type->tp_alloc(type, 0); /* starts with 1 ref, used for the return ref' */ + ret->ref= base->ref; + base->ref= NULL; /* invalidate! disallow further access */ + + ret->py_owns= base->py_owns; + + ret->ref->m_proxy= NULL; + + /* 'base' may be free'd after this func finished but not necessarily + * there is no reference to the BGE data now so it will throw an error on access */ + Py_DECREF(base); + + ret->ref->m_proxy= (PyObject *)ret; /* no need to add a ref because one is added when creating. */ + Py_INCREF(ret); /* we return a new ref but m_proxy holds a ref so we need to add one */ + + + /* 'ret' will have 2 references. + * - One ref is needed because ret->ref->m_proxy holds a refcount to the current proxy. + * - Another is needed for returning the value. + * + * So we should be ok with 2 refs, but for some reason this crashes. so adding a new ref... + * */ + + return (PyObject *)ret; } -PyObject* PyObjectPlus::py_getattro_dict() { - return py_getattr_dict(NULL, Type.tp_dict); -} - -int PyObjectPlus::py_delattro(PyObject* attr) +void PyObjectPlus::py_base_dealloc(PyObject *self) // python wrapper { - PyErr_SetString(PyExc_AttributeError, "attribute cant be deleted"); - return 1; + PyObjectPlus *self_plus= BGE_PROXY_REF(self); + if(self_plus) { + if(BGE_PROXY_PYOWNS(self)) { /* Does python own this?, then delete it */ + self_plus->m_proxy = NULL; /* Need this to stop ~PyObjectPlus from decrefing m_proxy otherwise its decref'd twice and py-debug crashes */ + delete self_plus; + } + + BGE_PROXY_REF(self)= NULL; // not really needed + } + +#if 0 + /* is ok normally but not for subtyping, use tp_free instead. */ + PyObject_DEL( self ); +#else + Py_TYPE(self)->tp_free(self); +#endif +}; + +PyObjectPlus::PyObjectPlus() : SG_QList() // constructor +{ + m_proxy= NULL; +}; + +/*------------------------------ + * PyObjectPlus Methods -- Every class, even the abstract one should have a Methods +------------------------------*/ +PyMethodDef PyObjectPlus::Methods[] = { + {NULL, NULL} /* Sentinel */ +}; + +#define attr_invalid (&(PyObjectPlus::Attributes[0])) +PyAttributeDef PyObjectPlus::Attributes[] = { + KX_PYATTRIBUTE_RO_FUNCTION("invalid", PyObjectPlus, pyattr_get_invalid), + {NULL} //Sentinel +}; + + + +PyObject* PyObjectPlus::pyattr_get_invalid(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + return PyBool_FromLong(self_v ? 1:0); } -int PyObjectPlus::py_setattro(PyObject *attr, PyObject* value) +/* note, this is called as a python 'getset, where the PyAttributeDef is the closure */ +PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef *attrdef) { - PyErr_SetString(PyExc_AttributeError, "attribute cant be set"); - return PY_SET_ATTR_MISSING; -} + void *self= (void *)(BGE_PROXY_REF(self_py)); + if(self==NULL) { + if(attrdef == attr_invalid) + Py_RETURN_TRUE; // dont bother running the function + + PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG); + return NULL; + } + -PyObject *PyObjectPlus::py_get_attrdef(void *self, const PyAttributeDef *attrdef) -{ if (attrdef->m_type == KX_PYATTRIBUTE_TYPE_DUMMY) { // fake attribute, ignore @@ -259,14 +256,14 @@ PyObject *PyObjectPlus::py_get_attrdef(void *self, const PyAttributeDef *attrdef { bool *val = reinterpret_cast(ptr); ptr += sizeof(bool); - PyList_SET_ITEM(resultlist,i,PyInt_FromLong(*val)); + PyList_SET_ITEM(resultlist,i,PyLong_FromSsize_t(*val)); break; } case KX_PYATTRIBUTE_TYPE_SHORT: { short int *val = reinterpret_cast(ptr); ptr += sizeof(short int); - PyList_SET_ITEM(resultlist,i,PyInt_FromLong(*val)); + PyList_SET_ITEM(resultlist,i,PyLong_FromSsize_t(*val)); break; } case KX_PYATTRIBUTE_TYPE_ENUM: @@ -281,7 +278,7 @@ PyObject *PyObjectPlus::py_get_attrdef(void *self, const PyAttributeDef *attrdef { int *val = reinterpret_cast(ptr); ptr += sizeof(int); - PyList_SET_ITEM(resultlist,i,PyInt_FromLong(*val)); + PyList_SET_ITEM(resultlist,i,PyLong_FromSsize_t(*val)); break; } case KX_PYATTRIBUTE_TYPE_FLOAT: @@ -305,12 +302,12 @@ PyObject *PyObjectPlus::py_get_attrdef(void *self, const PyAttributeDef *attrdef case KX_PYATTRIBUTE_TYPE_BOOL: { bool *val = reinterpret_cast(ptr); - return PyInt_FromLong(*val); + return PyLong_FromSsize_t(*val); } case KX_PYATTRIBUTE_TYPE_SHORT: { short int *val = reinterpret_cast(ptr); - return PyInt_FromLong(*val); + return PyLong_FromSsize_t(*val); } case KX_PYATTRIBUTE_TYPE_ENUM: // enum are like int, just make sure the field size is the same @@ -322,7 +319,7 @@ PyObject *PyObjectPlus::py_get_attrdef(void *self, const PyAttributeDef *attrdef case KX_PYATTRIBUTE_TYPE_INT: { int *val = reinterpret_cast(ptr); - return PyInt_FromLong(*val); + return PyLong_FromSsize_t(*val); } case KX_PYATTRIBUTE_TYPE_FLOAT: { @@ -334,7 +331,7 @@ PyObject *PyObjectPlus::py_get_attrdef(void *self, const PyAttributeDef *attrdef MT_Vector3 *val = reinterpret_cast(ptr); #ifdef USE_MATHUTILS float fval[3]= {(*val)[0], (*val)[1], (*val)[2]}; - return newVectorObject(fval, 3, Py_NEW); + return newVectorObject(fval, 3, Py_NEW, NULL); #else PyObject* resultlist = PyList_New(3); for (unsigned int i=0; i<3; i++) @@ -347,7 +344,7 @@ PyObject *PyObjectPlus::py_get_attrdef(void *self, const PyAttributeDef *attrdef case KX_PYATTRIBUTE_TYPE_STRING: { STR_String *val = reinterpret_cast(ptr); - return PyString_FromString(*val); + return PyUnicode_FromString(*val); } default: return NULL; @@ -355,8 +352,15 @@ PyObject *PyObjectPlus::py_get_attrdef(void *self, const PyAttributeDef *attrdef } } -int PyObjectPlus::py_set_attrdef(void *self, const PyAttributeDef *attrdef, PyObject *value) +/* note, this is called as a python getset */ +int PyObjectPlus::py_set_attrdef(PyObject *self_py, PyObject *value, const PyAttributeDef *attrdef) { + void *self= (void *)(BGE_PROXY_REF(self_py)); + if(self==NULL) { + PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG); + return PY_SET_ATTR_FAIL; + } + void *undoBuffer = NULL; void *sourceBuffer = NULL; size_t bufferSize = 0; @@ -421,9 +425,9 @@ int PyObjectPlus::py_set_attrdef(void *self, const PyAttributeDef *attrdef, PyOb { bool *var = reinterpret_cast(ptr); ptr += sizeof(bool); - if (PyInt_Check(item)) + if (PyLong_Check(item)) { - *var = (PyInt_AsLong(item) != 0); + *var = (PyLong_AsSsize_t(item) != 0); } else if (PyBool_Check(item)) { @@ -440,9 +444,9 @@ int PyObjectPlus::py_set_attrdef(void *self, const PyAttributeDef *attrdef, PyOb { short int *var = reinterpret_cast(ptr); ptr += sizeof(short int); - if (PyInt_Check(item)) + if (PyLong_Check(item)) { - long val = PyInt_AsLong(item); + long val = PyLong_AsSsize_t(item); if (attrdef->m_clamp) { if (val < attrdef->m_imin) @@ -476,9 +480,9 @@ int PyObjectPlus::py_set_attrdef(void *self, const PyAttributeDef *attrdef, PyOb { int *var = reinterpret_cast(ptr); ptr += sizeof(int); - if (PyInt_Check(item)) + if (PyLong_Check(item)) { - long val = PyInt_AsLong(item); + long val = PyLong_AsSsize_t(item); if (attrdef->m_clamp) { if (val < attrdef->m_imin) @@ -611,9 +615,9 @@ int PyObjectPlus::py_set_attrdef(void *self, const PyAttributeDef *attrdef, PyOb case KX_PYATTRIBUTE_TYPE_BOOL: { bool *var = reinterpret_cast(ptr); - if (PyInt_Check(value)) + if (PyLong_Check(value)) { - *var = (PyInt_AsLong(value) != 0); + *var = (PyLong_AsSsize_t(value) != 0); } else if (PyBool_Check(value)) { @@ -629,9 +633,9 @@ int PyObjectPlus::py_set_attrdef(void *self, const PyAttributeDef *attrdef, PyOb case KX_PYATTRIBUTE_TYPE_SHORT: { short int *var = reinterpret_cast(ptr); - if (PyInt_Check(value)) + if (PyLong_Check(value)) { - long val = PyInt_AsLong(value); + long val = PyLong_AsSsize_t(value); if (attrdef->m_clamp) { if (val < attrdef->m_imin) @@ -664,9 +668,9 @@ int PyObjectPlus::py_set_attrdef(void *self, const PyAttributeDef *attrdef, PyOb case KX_PYATTRIBUTE_TYPE_INT: { int *var = reinterpret_cast(ptr); - if (PyInt_Check(value)) + if (PyLong_Check(value)) { - long val = PyInt_AsLong(value); + long val = PyLong_AsSsize_t(value); if (attrdef->m_clamp) { if (val < attrdef->m_imin) @@ -751,9 +755,9 @@ int PyObjectPlus::py_set_attrdef(void *self, const PyAttributeDef *attrdef, PyOb case KX_PYATTRIBUTE_TYPE_STRING: { STR_String *var = reinterpret_cast(ptr); - if (PyString_Check(value)) + if (PyUnicode_Check(value)) { - char *val = PyString_AsString(value); + char *val = _PyUnicode_AsString(value); if (attrdef->m_clamp) { if (strlen(val) < attrdef->m_imin) @@ -834,48 +838,6 @@ PyObject *PyObjectPlus::py_repr(void) return NULL; } -/*------------------------------ - * PyObjectPlus isA -- the isA functions -------------------------------*/ -bool PyObjectPlus::isA(PyTypeObject *T) // if called with a Type, use "typename" -{ - int i; - PyParentObject P; - PyParentObject *Ps = GetParents(); - - for (P = Ps[i=0]; P != NULL; P = Ps[i++]) - if (P==T) - return true; - - return false; -} - - -bool PyObjectPlus::isA(const char *mytypename) // check typename of each parent -{ - int i; - PyParentObject P; - PyParentObject *Ps = GetParents(); - - for (P = Ps[i=0]; P != NULL; P = Ps[i++]) - if (strcmp(P->tp_name, mytypename)==0) - return true; - - return false; -} - -PyObject *PyObjectPlus::PyisA(PyObject *value) // Python wrapper for isA -{ - if (PyType_Check(value)) { - return PyBool_FromLong(isA((PyTypeObject *)value)); - } else if (PyString_Check(value)) { - return PyBool_FromLong(isA(PyString_AsString(value))); - } - PyErr_SetString(PyExc_TypeError, "object.isA(value): expected a type or a string"); - return NULL; -} - - void PyObjectPlus::ProcessReplica() { /* Clear the proxy, will be created again if needed with GetProxy() @@ -900,27 +862,6 @@ void PyObjectPlus::InvalidateProxy() // check typename of each parent } } -/* Utility function called by the macro py_getattro_up() - * for getting ob.__dict__() values from our PyObject - * this is used by python for doing dir() on an object, so its good - * if we return a list of attributes and methods. - * - * Other then making dir() useful the value returned from __dict__() is not useful - * since every value is a Py_None - * */ -PyObject *py_getattr_dict(PyObject *pydict, PyObject *tp_dict) -{ - if(pydict==NULL) { /* incase calling __dict__ on the parent of this object raised an error */ - PyErr_Clear(); - pydict = PyDict_New(); - } - - PyDict_Update(pydict, tp_dict); - return pydict; -} - - - PyObject *PyObjectPlus::GetProxy_Ext(PyObjectPlus *self, PyTypeObject *tp) { if (self->m_proxy==NULL) @@ -991,7 +932,7 @@ void PyObjectPlus::ShowDeprecationWarning_func(const char* old_way,const char* n co_filename= PyObject_GetAttrString(f_code, "co_filename"); if (co_filename) { - printf("\t%s:%d\n", PyString_AsString(co_filename), (int)PyInt_AsLong(f_lineno)); + printf("\t%s:%d\n", _PyUnicode_AsString(co_filename), (int)PyLong_AsSsize_t(f_lineno)); Py_DECREF(f_lineno); Py_DECREF(f_code); diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/PyObjectPlus.h index 3b5eebe9893..a18df9d36a9 100644 --- a/source/gameengine/Expressions/PyObjectPlus.h +++ b/source/gameengine/Expressions/PyObjectPlus.h @@ -51,19 +51,9 @@ extern "C" { } #endif -#if PY_VERSION_HEX > 0x03000000 -#define PyString_FromString PyUnicode_FromString -#define PyString_FromFormat PyUnicode_FromFormat -#define PyString_Check PyUnicode_Check -#define PyString_Size PyUnicode_GetSize - -#define PyInt_FromLong PyLong_FromSsize_t -#define PyInt_AsLong PyLong_AsSsize_t -#define PyString_AsString _PyUnicode_AsString -#define PyInt_Check PyLong_Check -#define PyInt_AS_LONG PyLong_AsLong // TODO - check this one -#endif - +extern "C" { +#include "../../blender/python/intern/bpy_compat.h" +} /* @@ -145,7 +135,7 @@ typedef struct { #define BGE_PROXY_PYOWNS(_self) (((PyObjectPlus_Proxy *)_self)->py_owns) /* Note, sometimes we dont care what BGE type this is as long as its a proxy */ -#define BGE_PROXY_CHECK_TYPE(_self) ((_self)->ob_type->tp_dealloc == PyObjectPlus::py_base_dealloc) +#define BGE_PROXY_CHECK_TYPE(_type) ((_type)->tp_dealloc == PyObjectPlus::py_base_dealloc) // This must be the first line of each @@ -155,41 +145,10 @@ typedef struct { static PyTypeObject Type; \ static PyMethodDef Methods[]; \ static PyAttributeDef Attributes[]; \ - static PyParentObject Parents[]; \ virtual PyTypeObject *GetType(void) {return &Type;}; \ - virtual PyParentObject *GetParents(void) {return Parents;} \ virtual PyObject *GetProxy() {return GetProxy_Ext(this, &Type);}; \ virtual PyObject *NewProxy(bool py_owns) {return NewProxy_Ext(this, &Type, py_owns);}; \ - - - - // This defines the py_getattro_up macro - // which allows attribute and method calls - // to be properly passed up the hierarchy. - // - // Note, PyDict_GetItem() WONT set an exception! - // let the py_base_getattro function do this. - -#define py_getattro_up(Parent) \ - \ - PyObject *descr = PyDict_GetItem(Type.tp_dict, attr); \ - \ - if(descr) { \ - if (PyCObject_Check(descr)) { \ - return py_get_attrdef((void *)this, (const PyAttributeDef*)PyCObject_AsVoidPtr(descr)); \ - } else if (descr->ob_type->tp_descr_get) { \ - return PyCFunction_New(((PyMethodDescrObject *)descr)->d_method, this->m_proxy); \ - } else { \ - return NULL; \ - } \ - } else { \ - return Parent::py_getattro(attr); \ - } - -#define py_getattro_dict_up(Parent) \ - return py_getattr_dict(Parent::py_getattro_dict(), Type.tp_dict); - /* * nonzero values are an error for setattr * however because of the nested lookups we need to know if the errors @@ -201,29 +160,6 @@ typedef struct { #define PY_SET_ATTR_MISSING -1 #define PY_SET_ATTR_SUCCESS 0 -#define py_setattro_up(Parent) \ - PyObject *descr = PyDict_GetItem(Type.tp_dict, attr); \ - \ - if(descr) { \ - if (PyCObject_Check(descr)) { \ - const PyAttributeDef* attrdef= reinterpret_cast(PyCObject_AsVoidPtr(descr)); \ - if (attrdef->m_access == KX_PYATTRIBUTE_RO) { \ - PyErr_Format(PyExc_AttributeError, "\"%s\" is read only", PyString_AsString(attr)); \ - return PY_SET_ATTR_FAIL; \ - } \ - else { \ - return py_set_attrdef((void *)this, attrdef, value); \ - } \ - } else { \ - PyErr_Format(PyExc_AttributeError, "\"%s\" cannot be set", PyString_AsString(attr)); \ - return PY_SET_ATTR_FAIL; \ - } \ - } else { \ - PyErr_Clear(); \ - return Parent::py_setattro(attr, value); \ - } - - /** * These macros are helpfull when embedding Python routines. The second * macro is one that also requires a documentation string @@ -493,7 +429,7 @@ class PyObjectPlus : public SG_QList Py_Header; // Always start with Py_Header public: - PyObjectPlus(PyTypeObject *T); + PyObjectPlus(); PyObject *m_proxy; /* actually a PyObjectPlus_Proxy */ @@ -501,30 +437,19 @@ public: /* These static functions are referenced by ALL PyObjectPlus_Proxy types * they take the C++ reference from the PyObjectPlus_Proxy and call - * its own virtual py_getattro, py_setattro etc. functions. + * its own virtual py_repr, py_base_dealloc ,etc. functions. */ + + static PyObject* py_base_new(PyTypeObject *type, PyObject *args, PyObject *kwds); /* allows subclassing */ static void py_base_dealloc(PyObject *self); - static PyObject* py_base_getattro(PyObject * self, PyObject *attr); - static int py_base_setattro(PyObject *self, PyObject *attr, PyObject *value); static PyObject* py_base_repr(PyObject *self); /* These are all virtual python methods that are defined in each class * Our own fake subclassing calls these on each class, then calls the parent */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_delattro(PyObject *attr); - virtual int py_setattro(PyObject *attr, PyObject *value); virtual PyObject* py_repr(void); - static PyObject* py_get_attrdef(void *self, const PyAttributeDef *attrdef); - static int py_set_attrdef(void *self, const PyAttributeDef *attrdef, PyObject *value); - - /* isA() methods, shonky replacement for pythons issubclass() - * which we cant use because we have our own subclass system */ - bool isA(PyTypeObject *T); - bool isA(const char *mytypename); - - KX_PYMETHOD_O(PyObjectPlus,isA); + static PyObject* py_get_attrdef(PyObject *self_py, const PyAttributeDef *attrdef); + static int py_set_attrdef(PyObject *self_py, PyObject *value, const PyAttributeDef *attrdef); /* Kindof dumb, always returns True, the false case is checked for, before this function gets accessed */ static PyObject* pyattr_get_invalid(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); diff --git a/source/gameengine/Expressions/StringValue.h b/source/gameengine/Expressions/StringValue.h index 52f8a580f4d..c580e8fd23a 100644 --- a/source/gameengine/Expressions/StringValue.h +++ b/source/gameengine/Expressions/StringValue.h @@ -40,7 +40,7 @@ public: virtual void SetValue(CValue* newval) { m_strString = newval->GetText(); SetModified(true); }; virtual CValue* GetReplica(); virtual PyObject* ConvertValueToPython() { - return PyString_FromString(m_strString.Ptr()); + return PyUnicode_FromString(m_strString.Ptr()); } private: diff --git a/source/gameengine/Expressions/Value.cpp b/source/gameengine/Expressions/Value.cpp index 61dabff510b..d8c81f56f66 100644 --- a/source/gameengine/Expressions/Value.cpp +++ b/source/gameengine/Expressions/Value.cpp @@ -54,15 +54,17 @@ PyTypeObject CValue::Type = { py_base_repr, 0, 0,0,0,0,0, - py_base_getattro, - py_base_setattro, - 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject CValue::Parents[] = { - &CValue::Type, - NULL + NULL, + NULL, + 0, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, + &PyObjectPlus::Type, + 0,0,0,0,0,0, + py_base_new }; PyMethodDef CValue::Methods[] = { @@ -74,7 +76,7 @@ PyObject* CValue::PyGetName() { ShowDeprecationWarning("getName()", "the name property"); - return PyString_FromString(this->GetName()); + return PyUnicode_FromString(this->GetName()); } /*#define CVALUE_DEBUG*/ @@ -100,8 +102,8 @@ std::vector gRefList; //int gRefCountValue; #endif -CValue::CValue(PyTypeObject *T) - : PyObjectPlus(T), +CValue::CValue() + : PyObjectPlus(), #else CValue::CValue() : @@ -553,33 +555,9 @@ PyAttributeDef CValue::Attributes[] = { { NULL } //Sentinel }; - -PyObject* CValue::py_getattro(PyObject *attr) -{ - char *attr_str= PyString_AsString(attr); - CValue* resultattr = GetProperty(attr_str); - if (resultattr) - { - /* only show the wanting here because python inspects for __class__ and KX_MeshProxy uses CValues name attr */ - ShowDeprecationWarning("val = ob.attr", "val = ob['attr']"); - - PyObject* pyconvert = resultattr->ConvertValueToPython(); - - if (pyconvert) - return pyconvert; - else - return resultattr->GetProxy(); - } - py_getattro_up(PyObjectPlus); -} - -PyObject* CValue::py_getattro_dict() { - py_getattro_dict_up(PyObjectPlus); -} - PyObject * CValue::pyattr_get_name(void * self_v, const KX_PYATTRIBUTE_DEF * attrdef) { CValue * self = static_cast (self_v); - return PyString_FromString(self->GetName()); + return PyUnicode_FromString(self->GetName()); } CValue* CValue::ConvertPythonToValue(PyObject* pyobj, const char *error_prefix) @@ -623,30 +601,23 @@ CValue* CValue::ConvertPythonToValue(PyObject* pyobj, const char *error_prefix) { vallie = new CFloatValue( (float)PyFloat_AsDouble(pyobj) ); } else +#if PY_VERSION_HEX < 0x03000000 if (PyInt_Check(pyobj)) { vallie = new CIntValue( (cInt)PyInt_AS_LONG(pyobj) ); } else +#endif if (PyLong_Check(pyobj)) { vallie = new CIntValue( (cInt)PyLong_AsLongLong(pyobj) ); } else - if (PyString_Check(pyobj)) + if (PyUnicode_Check(pyobj)) { - vallie = new CStringValue(PyString_AsString(pyobj),""); + vallie = new CStringValue(_PyUnicode_AsString(pyobj),""); } else - if (BGE_PROXY_CHECK_TYPE(pyobj)) /* Note, dont let these get assigned to GameObject props, must check elsewhere */ + if (PyObject_TypeCheck(pyobj, &CValue::Type)) /* Note, dont let these get assigned to GameObject props, must check elsewhere */ { - if (BGE_PROXY_REF(pyobj) && (BGE_PROXY_REF(pyobj))->isA(&CValue::Type)) - { - vallie = (static_cast(BGE_PROXY_REF(pyobj)))->AddRef(); - } else { - - if(BGE_PROXY_REF(pyobj)) /* this is not a CValue */ - PyErr_Format(PyExc_TypeError, "%sgame engine python type cannot be used as a property", error_prefix); - else /* PyObjectPlus_Proxy has been removed, cant use */ - PyErr_Format(PyExc_SystemError, "%s"BGE_PROXY_ERROR_MSG, error_prefix); - } + vallie = (static_cast(BGE_PROXY_REF(pyobj)))->AddRef(); } else { /* return an error value from the caller */ @@ -656,57 +627,6 @@ CValue* CValue::ConvertPythonToValue(PyObject* pyobj, const char *error_prefix) } -int CValue::py_delattro(PyObject *attr) -{ - ShowDeprecationWarning("del ob.attr", "del ob['attr']"); - - char *attr_str= PyString_AsString(attr); - if (RemoveProperty(attr_str)) - return 0; - - PyErr_Format(PyExc_AttributeError, "attribute \"%s\" dosnt exist", attr_str); - return PY_SET_ATTR_MISSING; -} - -int CValue::py_setattro(PyObject *attr, PyObject* pyobj) -{ - ShowDeprecationWarning("ob.attr = val", "ob['attr'] = val"); - - char *attr_str= PyString_AsString(attr); - CValue* oldprop = GetProperty(attr_str); - CValue* vallie; - - /* Dissallow python to assign GameObjects, Scenes etc as values */ - if ((BGE_PROXY_CHECK_TYPE(pyobj)==0) && (vallie = ConvertPythonToValue(pyobj, "cvalue.attr = value: "))) - { - if (oldprop) - oldprop->SetValue(vallie); - else - SetProperty(attr_str, vallie); - - vallie->Release(); - } - else { - // ConvertPythonToValue sets the error message - // must return missing so KX_GameObect knows this - // attribute was not a function or bult in attribute, - // - // CValue attributes override internal attributes - // so if it exists as a CValue attribute already, - // assume your trying to set it to a differnt CValue attribute - // otherwise return PY_SET_ATTR_MISSING so children - // classes know they can set it without conflict - - if (GetProperty(attr_str)) - return PY_SET_ATTR_COERCE_FAIL; /* failed to set an existing attribute */ - else - return PY_SET_ATTR_MISSING; /* allow the KX_GameObject dict to set */ - } - - //PyObjectPlus::py_setattro(attr,value); - return PY_SET_ATTR_SUCCESS; -}; - PyObject* CValue::ConvertKeysToPython( void ) { PyObject *pylist = PyList_New( 0 ); @@ -717,7 +637,7 @@ PyObject* CValue::ConvertKeysToPython( void ) std::map::iterator it; for (it= m_pNamedPropertyArray->begin(); (it != m_pNamedPropertyArray->end()); it++) { - pystr = PyString_FromString( (*it).first ); + pystr = PyUnicode_FromString( (*it).first ); PyList_Append(pylist, pystr); Py_DECREF( pystr ); } diff --git a/source/gameengine/Expressions/Value.h b/source/gameengine/Expressions/Value.h index 29ef19b46c9..8c9f99b335e 100644 --- a/source/gameengine/Expressions/Value.h +++ b/source/gameengine/Expressions/Value.h @@ -215,26 +215,18 @@ public: // Construction / Destruction #ifndef NO_EXP_PYTHON_EMBEDDING - CValue(PyTypeObject *T = &Type); + CValue(); //static PyObject* PyMake(PyObject*,PyObject*); virtual PyObject *py_repr(void) { - return PyString_FromString((const char*)GetText()); + return PyUnicode_FromString((const char*)GetText()); } - - - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); virtual PyObject* ConvertValueToPython() { return NULL; } virtual CValue* ConvertPythonToValue(PyObject* pyobj, const char *error_prefix); - - - virtual int py_delattro(PyObject *attr); - virtual int py_setattro(PyObject *attr, PyObject* value); static PyObject * pyattr_get_name(void * self, const KX_PYATTRIBUTE_DEF * attrdef); @@ -417,8 +409,8 @@ class CPropValue : public CValue public: #ifndef NO_EXP_PYTHON_EMBEDDING - CPropValue(PyTypeObject* T=&Type) : - CValue(T), + CPropValue() : + CValue(), #else CPropValue() : #endif //NO_EXP_PYTHON_EMBEDDING diff --git a/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp b/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp index caed85b9938..04d46e259d3 100644 --- a/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp +++ b/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp @@ -42,9 +42,8 @@ SCA_2DFilterActuator::SCA_2DFilterActuator( float float_arg, int int_arg, RAS_IRasterizer* rasterizer, - RAS_IRenderTools* rendertools, - PyTypeObject* T) - : SCA_IActuator(gameobj, T), + RAS_IRenderTools* rendertools) + : SCA_IActuator(gameobj), m_type(type), m_disableMotionBlur(flag), m_float_arg(float_arg), @@ -124,23 +123,17 @@ PyTypeObject SCA_2DFilterActuator::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, + &SCA_IActuator::Type, + 0,0,0,0,0,0, + py_base_new }; - -PyParentObject SCA_2DFilterActuator::Parents[] = { - &SCA_2DFilterActuator::Type, - &SCA_IActuator::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL -}; - - PyMethodDef SCA_2DFilterActuator::Methods[] = { /* add python functions to deal with m_msg... */ {NULL,NULL} @@ -154,18 +147,3 @@ PyAttributeDef SCA_2DFilterActuator::Attributes[] = { KX_PYATTRIBUTE_FLOAT_RW("value", 0.0, 100.0, SCA_2DFilterActuator, m_float_arg), { NULL } //Sentinel }; - -PyObject* SCA_2DFilterActuator::py_getattro(PyObject *attr) -{ - py_getattro_up(SCA_IActuator); -} - -PyObject* SCA_2DFilterActuator::py_getattro_dict() { - py_getattro_dict_up(SCA_IActuator); -} - -int SCA_2DFilterActuator::py_setattro(PyObject *attr, PyObject* value) -{ - py_setattro_up(SCA_IActuator); -} - diff --git a/source/gameengine/GameLogic/SCA_2DFilterActuator.h b/source/gameengine/GameLogic/SCA_2DFilterActuator.h index 13b9997a010..c357c4f3e37 100644 --- a/source/gameengine/GameLogic/SCA_2DFilterActuator.h +++ b/source/gameengine/GameLogic/SCA_2DFilterActuator.h @@ -56,23 +56,12 @@ public: float float_arg, int int_arg, RAS_IRasterizer* rasterizer, - RAS_IRenderTools* rendertools, - PyTypeObject* T=&Type - ); + RAS_IRenderTools* rendertools); void SetShaderText(const char *text); virtual ~SCA_2DFilterActuator(); virtual bool Update(); virtual CValue* GetReplica(); - - /* --------------------------------------------------------------------- */ - /* Python interface ---------------------------------------------------- */ - /* --------------------------------------------------------------------- */ - - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject* value); - }; #endif diff --git a/source/gameengine/GameLogic/SCA_ANDController.cpp b/source/gameengine/GameLogic/SCA_ANDController.cpp index 87f7c612e7c..78e1350428e 100644 --- a/source/gameengine/GameLogic/SCA_ANDController.cpp +++ b/source/gameengine/GameLogic/SCA_ANDController.cpp @@ -42,10 +42,9 @@ /* Native functions */ /* ------------------------------------------------------------------------- */ -SCA_ANDController::SCA_ANDController(SCA_IObject* gameobj, - PyTypeObject* T) +SCA_ANDController::SCA_ANDController(SCA_IObject* gameobj) : - SCA_IController(gameobj,T) + SCA_IController(gameobj) { } @@ -116,19 +115,15 @@ PyTypeObject SCA_ANDController::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject SCA_ANDController::Parents[] = { - &SCA_ANDController::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IController::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef SCA_ANDController::Methods[] = { @@ -139,12 +134,4 @@ PyAttributeDef SCA_ANDController::Attributes[] = { { NULL } //Sentinel }; -PyObject* SCA_ANDController::py_getattro(PyObject *attr) { - py_getattro_up(SCA_IController); -} - -PyObject* SCA_ANDController::py_getattro_dict() { - py_getattro_dict_up(SCA_IController); -} - /* eof */ diff --git a/source/gameengine/GameLogic/SCA_ANDController.h b/source/gameengine/GameLogic/SCA_ANDController.h index 9a359d57cb4..cb16d7fca01 100644 --- a/source/gameengine/GameLogic/SCA_ANDController.h +++ b/source/gameengine/GameLogic/SCA_ANDController.h @@ -39,18 +39,10 @@ class SCA_ANDController : public SCA_IController Py_Header; //virtual void Trigger(class SCA_LogicManager* logicmgr); public: - SCA_ANDController(SCA_IObject* gameobj,PyTypeObject* T=&Type); + SCA_ANDController(SCA_IObject* gameobj); virtual ~SCA_ANDController(); virtual CValue* GetReplica(); virtual void Trigger(SCA_LogicManager* logicmgr); - - /* --------------------------------------------------------------------- */ - /* Python interface ---------------------------------------------------- */ - /* --------------------------------------------------------------------- */ - - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - }; #endif //__KX_ANDCONTROLLER diff --git a/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp b/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp index 4dad65c5a25..bdcc923e1d9 100644 --- a/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp +++ b/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp @@ -40,9 +40,8 @@ SCA_ActuatorSensor::SCA_ActuatorSensor(SCA_EventManager* eventmgr, SCA_IObject* gameobj, - const STR_String& actname, - PyTypeObject* T ) - : SCA_ISensor(gameobj,eventmgr,T), + const STR_String& actname) + : SCA_ISensor(gameobj,eventmgr), m_checkactname(actname) { m_actuator = GetParent()->FindActuator(m_checkactname); @@ -138,19 +137,15 @@ PyTypeObject SCA_ActuatorSensor::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject SCA_ActuatorSensor::Parents[] = { - &SCA_ActuatorSensor::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_ISensor::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef SCA_ActuatorSensor::Methods[] = { @@ -166,18 +161,6 @@ PyAttributeDef SCA_ActuatorSensor::Attributes[] = { { NULL } //Sentinel }; -PyObject* SCA_ActuatorSensor::py_getattro(PyObject *attr) { - py_getattro_up(SCA_ISensor); -} - -PyObject* SCA_ActuatorSensor::py_getattro_dict() { - py_getattro_dict_up(SCA_ISensor); -} - -int SCA_ActuatorSensor::py_setattro(PyObject *attr, PyObject *value) { - py_setattro_up(SCA_ISensor); -} - int SCA_ActuatorSensor::CheckActuator(void *self, const PyAttributeDef*) { SCA_ActuatorSensor* sensor = reinterpret_cast(self); @@ -197,7 +180,7 @@ const char SCA_ActuatorSensor::GetActuator_doc[] = PyObject* SCA_ActuatorSensor::PyGetActuator() { ShowDeprecationWarning("getActuator()", "the actuator property"); - return PyString_FromString(m_checkactname); + return PyUnicode_FromString(m_checkactname); } /* 4. setActuator */ diff --git a/source/gameengine/GameLogic/SCA_ActuatorSensor.h b/source/gameengine/GameLogic/SCA_ActuatorSensor.h index 6655e08dc70..cf8e735cad4 100644 --- a/source/gameengine/GameLogic/SCA_ActuatorSensor.h +++ b/source/gameengine/GameLogic/SCA_ActuatorSensor.h @@ -46,8 +46,7 @@ class SCA_ActuatorSensor : public SCA_ISensor public: SCA_ActuatorSensor(class SCA_EventManager* eventmgr, SCA_IObject* gameobj, - const STR_String& actname, - PyTypeObject* T=&Type ); + const STR_String& actname); virtual ~SCA_ActuatorSensor(); virtual CValue* GetReplica(); @@ -61,10 +60,6 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); - /* 3. setProperty */ KX_PYMETHOD_DOC_VARARGS(SCA_ActuatorSensor,SetActuator); /* 4. getProperty */ diff --git a/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp b/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp index ff02680f191..ddb54c580b8 100644 --- a/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp +++ b/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp @@ -48,9 +48,8 @@ /* ------------------------------------------------------------------------- */ SCA_AlwaysSensor::SCA_AlwaysSensor(class SCA_EventManager* eventmgr, - SCA_IObject* gameobj, - PyTypeObject* T) - : SCA_ISensor(gameobj,eventmgr, T) + SCA_IObject* gameobj) + : SCA_ISensor(gameobj,eventmgr) { //SetDrawColor(255,0,0); Init(); @@ -121,19 +120,15 @@ PyTypeObject SCA_AlwaysSensor::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject SCA_AlwaysSensor::Parents[] = { - &SCA_AlwaysSensor::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_ISensor::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef SCA_AlwaysSensor::Methods[] = { @@ -144,12 +139,4 @@ PyAttributeDef SCA_AlwaysSensor::Attributes[] = { { NULL } //Sentinel }; -PyObject* SCA_AlwaysSensor::py_getattro(PyObject *attr) { - py_getattro_up(SCA_ISensor); -} - -PyObject* SCA_AlwaysSensor::py_getattro_dict() { - py_getattro_dict_up(SCA_ISensor); -} - /* eof */ diff --git a/source/gameengine/GameLogic/SCA_AlwaysSensor.h b/source/gameengine/GameLogic/SCA_AlwaysSensor.h index 0f85a641ef1..d58e05564d1 100644 --- a/source/gameengine/GameLogic/SCA_AlwaysSensor.h +++ b/source/gameengine/GameLogic/SCA_AlwaysSensor.h @@ -39,22 +39,12 @@ class SCA_AlwaysSensor : public SCA_ISensor bool m_alwaysresult; public: SCA_AlwaysSensor(class SCA_EventManager* eventmgr, - SCA_IObject* gameobj, - PyTypeObject* T =&Type); + SCA_IObject* gameobj); virtual ~SCA_AlwaysSensor(); virtual CValue* GetReplica(); virtual bool Evaluate(); virtual bool IsPositiveTrigger(); virtual void Init(); - - - /* --------------------------------------------------------------------- */ - /* Python interface ---------------------------------------------------- */ - /* --------------------------------------------------------------------- */ - - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - }; #endif //__KX_ALWAYSSENSOR diff --git a/source/gameengine/GameLogic/SCA_DelaySensor.cpp b/source/gameengine/GameLogic/SCA_DelaySensor.cpp index dcdae0b4e75..11c6996a0a1 100644 --- a/source/gameengine/GameLogic/SCA_DelaySensor.cpp +++ b/source/gameengine/GameLogic/SCA_DelaySensor.cpp @@ -51,9 +51,8 @@ SCA_DelaySensor::SCA_DelaySensor(class SCA_EventManager* eventmgr, SCA_IObject* gameobj, int delay, int duration, - bool repeat, - PyTypeObject* T) - : SCA_ISensor(gameobj,eventmgr, T), + bool repeat) + : SCA_ISensor(gameobj,eventmgr), m_repeat(repeat), m_delay(delay), m_duration(duration) @@ -147,19 +146,15 @@ PyTypeObject SCA_DelaySensor::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject SCA_DelaySensor::Parents[] = { - &SCA_DelaySensor::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_ISensor::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef SCA_DelaySensor::Methods[] = { @@ -183,19 +178,6 @@ PyAttributeDef SCA_DelaySensor::Attributes[] = { { NULL } //Sentinel }; -PyObject* SCA_DelaySensor::py_getattro(PyObject *attr) { - py_getattro_up(SCA_ISensor); -} - -PyObject* SCA_DelaySensor::py_getattro_dict() { - py_getattro_dict_up(SCA_ISensor); -} - -int SCA_DelaySensor::py_setattro(PyObject *attr, PyObject *value) { - py_setattro_up(SCA_ISensor); -} - - const char SCA_DelaySensor::SetDelay_doc[] = "setDelay(delay)\n" "\t- delay: length of the initial OFF period as number of frame\n" @@ -262,7 +244,7 @@ const char SCA_DelaySensor::GetDelay_doc[] = PyObject* SCA_DelaySensor::PyGetDelay() { ShowDeprecationWarning("getDelay()", "the delay property"); - return PyInt_FromLong(m_delay); + return PyLong_FromSsize_t(m_delay); } const char SCA_DelaySensor::GetDuration_doc[] = @@ -271,7 +253,7 @@ const char SCA_DelaySensor::GetDuration_doc[] = PyObject* SCA_DelaySensor::PyGetDuration() { ShowDeprecationWarning("getDuration()", "the duration property"); - return PyInt_FromLong(m_duration); + return PyLong_FromSsize_t(m_duration); } const char SCA_DelaySensor::GetRepeat_doc[] = diff --git a/source/gameengine/GameLogic/SCA_DelaySensor.h b/source/gameengine/GameLogic/SCA_DelaySensor.h index 5ccb33f8a16..8270e8959b7 100644 --- a/source/gameengine/GameLogic/SCA_DelaySensor.h +++ b/source/gameengine/GameLogic/SCA_DelaySensor.h @@ -47,8 +47,7 @@ public: SCA_IObject* gameobj, int delay, int duration, - bool repeat, - PyTypeObject* T =&Type); + bool repeat); virtual ~SCA_DelaySensor(); virtual CValue* GetReplica(); virtual bool Evaluate(); @@ -59,10 +58,6 @@ public: /* --------------------------------------------------------------------- */ /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); /* setProperty */ KX_PYMETHOD_DOC_VARARGS(SCA_DelaySensor,SetDelay); diff --git a/source/gameengine/GameLogic/SCA_ExpressionController.cpp b/source/gameengine/GameLogic/SCA_ExpressionController.cpp index 8e044b89c71..60969300474 100644 --- a/source/gameengine/GameLogic/SCA_ExpressionController.cpp +++ b/source/gameengine/GameLogic/SCA_ExpressionController.cpp @@ -46,9 +46,8 @@ /* ------------------------------------------------------------------------- */ SCA_ExpressionController::SCA_ExpressionController(SCA_IObject* gameobj, - const STR_String& exprtext, - PyTypeObject* T) - :SCA_IController(gameobj,T), + const STR_String& exprtext) + :SCA_IController(gameobj), m_exprText(exprtext), m_exprCache(NULL) { diff --git a/source/gameengine/GameLogic/SCA_ExpressionController.h b/source/gameengine/GameLogic/SCA_ExpressionController.h index 6a34d7b2dff..705f6dfc415 100644 --- a/source/gameengine/GameLogic/SCA_ExpressionController.h +++ b/source/gameengine/GameLogic/SCA_ExpressionController.h @@ -42,8 +42,7 @@ class SCA_ExpressionController : public SCA_IController public: SCA_ExpressionController(SCA_IObject* gameobj, - const STR_String& exprtext, - PyTypeObject* T=&Type ); + const STR_String& exprtext); virtual ~SCA_ExpressionController(); virtual CValue* GetReplica(); @@ -54,14 +53,6 @@ public: * so that self references are removed before the controller itself is released */ virtual void Delete(); - - /* --------------------------------------------------------------------- */ - /* Python interface ---------------------------------------------------- */ - /* --------------------------------------------------------------------- */ - -// virtual PyObject* py_getattro(PyObject *attr); -// virtual PyObject* py_getattro_dict(); - }; #endif //__KX_EXPRESSIONCONTROLLER diff --git a/source/gameengine/GameLogic/SCA_IActuator.cpp b/source/gameengine/GameLogic/SCA_IActuator.cpp index be7c2651686..0fda75590c1 100644 --- a/source/gameengine/GameLogic/SCA_IActuator.cpp +++ b/source/gameengine/GameLogic/SCA_IActuator.cpp @@ -34,9 +34,8 @@ using namespace std; -SCA_IActuator::SCA_IActuator(SCA_IObject* gameobj, - PyTypeObject* T) : - SCA_ILogicBrick(gameobj,T), +SCA_IActuator::SCA_IActuator(SCA_IObject* gameobj) : + SCA_ILogicBrick(gameobj), m_links(0), m_posevent(false), m_negevent(false) diff --git a/source/gameengine/GameLogic/SCA_IActuator.h b/source/gameengine/GameLogic/SCA_IActuator.h index 27afcbc386b..13c718ee837 100644 --- a/source/gameengine/GameLogic/SCA_IActuator.h +++ b/source/gameengine/GameLogic/SCA_IActuator.h @@ -61,8 +61,7 @@ public: * This class also inherits the default copy constructors */ - SCA_IActuator(SCA_IObject* gameobj, - PyTypeObject* T =&Type); + SCA_IActuator(SCA_IObject* gameobj); /** * UnlinkObject(...) diff --git a/source/gameengine/GameLogic/SCA_IController.cpp b/source/gameengine/GameLogic/SCA_IController.cpp index f2c3c83a2d9..7cbb728753a 100644 --- a/source/gameengine/GameLogic/SCA_IController.cpp +++ b/source/gameengine/GameLogic/SCA_IController.cpp @@ -37,10 +37,9 @@ #include #endif -SCA_IController::SCA_IController(SCA_IObject* gameobj, - PyTypeObject* T) +SCA_IController::SCA_IController(SCA_IObject* gameobj) : - SCA_ILogicBrick(gameobj,T), + SCA_ILogicBrick(gameobj), m_statemask(0), m_justActivated(false) { @@ -216,17 +215,15 @@ PyTypeObject SCA_IController::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject SCA_IController::Parents[] = { - &SCA_IController::Type, - &CValue::Type, - NULL + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, + &SCA_ILogicBrick::Type, + 0,0,0,0,0,0, + py_base_new }; PyMethodDef SCA_IController::Methods[] = { @@ -248,22 +245,6 @@ PyAttributeDef SCA_IController::Attributes[] = { { NULL } //Sentinel }; -PyObject* SCA_IController::py_getattro(PyObject *attr) -{ - py_getattro_up(SCA_ILogicBrick); -} - -PyObject* SCA_IController::py_getattro_dict() { - py_getattro_dict_up(SCA_ILogicBrick); -} - -int SCA_IController::py_setattro(PyObject *attr, PyObject *value) -{ - py_setattro_up(SCA_ILogicBrick); -} - - - PyObject* SCA_IController::PyGetActuators() { ShowDeprecationWarning("getActuators()", "the actuators property"); @@ -281,7 +262,7 @@ PyObject* SCA_IController::PyGetSensor(PyObject* value) { ShowDeprecationWarning("getSensor(string)", "the sensors[string] property"); - char *scriptArg = PyString_AsString(value); + char *scriptArg = _PyUnicode_AsString(value); if (scriptArg==NULL) { PyErr_SetString(PyExc_TypeError, "controller.getSensor(string): Python Controller, expected a string (sensor name)"); return NULL; @@ -305,7 +286,7 @@ PyObject* SCA_IController::PyGetActuator(PyObject* value) { ShowDeprecationWarning("getActuator(string)", "the actuators[string] property"); - char *scriptArg = PyString_AsString(value); + char *scriptArg = _PyUnicode_AsString(value); if (scriptArg==NULL) { PyErr_SetString(PyExc_TypeError, "controller.getActuator(string): Python Controller, expected a string (actuator name)"); return NULL; @@ -340,13 +321,13 @@ PyObject* SCA_IController::PyGetSensors() PyObject* SCA_IController::PyGetState() { ShowDeprecationWarning("getState()", "the state property"); - return PyInt_FromLong(m_statemask); + return PyLong_FromSsize_t(m_statemask); } PyObject* SCA_IController::pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { SCA_IController* self= static_cast(self_v); - return PyInt_FromLong(self->m_statemask); + return PyLong_FromSsize_t(self->m_statemask); } PyObject* SCA_IController::pyattr_get_sensors(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) diff --git a/source/gameengine/GameLogic/SCA_IController.h b/source/gameengine/GameLogic/SCA_IController.h index a52c57ab3ed..523878bee26 100644 --- a/source/gameengine/GameLogic/SCA_IController.h +++ b/source/gameengine/GameLogic/SCA_IController.h @@ -47,7 +47,7 @@ protected: bool m_justActivated; bool m_bookmark; public: - SCA_IController(SCA_IObject* gameobj,PyTypeObject* T); + SCA_IController(SCA_IObject* gameobj); virtual ~SCA_IController(); virtual void Trigger(class SCA_LogicManager* logicmgr)=0; void LinkToSensor(SCA_ISensor* sensor); @@ -98,10 +98,6 @@ public: } } - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); - KX_PYMETHOD_NOARGS(SCA_IController,GetSensors); KX_PYMETHOD_NOARGS(SCA_IController,GetActuators); KX_PYMETHOD_O(SCA_IController,GetSensor); diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp index 2dc80f54568..ccb79a2d49f 100644 --- a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp +++ b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp @@ -35,10 +35,9 @@ SCA_LogicManager* SCA_ILogicBrick::m_sCurrentLogicManager = NULL; -SCA_ILogicBrick::SCA_ILogicBrick(SCA_IObject* gameobj, - PyTypeObject* T) +SCA_ILogicBrick::SCA_ILogicBrick(SCA_IObject* gameobj) : - CValue(T), + CValue(), m_gameobj(gameobj), m_Execute_Priority(0), m_Execute_Ueber_Priority(0), @@ -194,23 +193,17 @@ PyTypeObject SCA_ILogicBrick::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - - - -PyParentObject SCA_ILogicBrick::Parents[] = { - &SCA_ILogicBrick::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; - - PyMethodDef SCA_ILogicBrick::Methods[] = { // --> Deprecated {"getOwner", (PyCFunction) SCA_ILogicBrick::sPyGetOwner, METH_NOARGS}, @@ -245,21 +238,6 @@ int SCA_ILogicBrick::CheckProperty(void *self, const PyAttributeDef *attrdef) return 0; } -PyObject* SCA_ILogicBrick::py_getattro(PyObject *attr) -{ - py_getattro_up(CValue); -} - -PyObject* SCA_ILogicBrick::py_getattro_dict() { - py_getattro_dict_up(CValue); -} - -int SCA_ILogicBrick::py_setattro(PyObject *attr, PyObject *value) -{ - py_setattro_up(CValue); -} - - PyObject* SCA_ILogicBrick::PyGetOwner() { ShowDeprecationWarning("getOwner()", "the owner property"); @@ -296,7 +274,7 @@ PyObject* SCA_ILogicBrick::PySetExecutePriority(PyObject* args) PyObject* SCA_ILogicBrick::PyGetExecutePriority() { ShowDeprecationWarning("getExecutePriority()", "the executePriority property"); - return PyInt_FromLong(m_Execute_Priority); + return PyLong_FromSsize_t(m_Execute_Priority); } @@ -326,5 +304,5 @@ bool SCA_ILogicBrick::PyArgToBool(int boolArg) PyObject* SCA_ILogicBrick::BoolToPyArg(bool boolarg) { - return PyInt_FromLong(boolarg? KX_TRUE: KX_FALSE); + return PyLong_FromSsize_t(boolarg? KX_TRUE: KX_FALSE); } diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.h b/source/gameengine/GameLogic/SCA_ILogicBrick.h index 779e5397a6a..50679856802 100644 --- a/source/gameengine/GameLogic/SCA_ILogicBrick.h +++ b/source/gameengine/GameLogic/SCA_ILogicBrick.h @@ -53,7 +53,7 @@ protected: CValue* GetEvent(); public: - SCA_ILogicBrick(SCA_IObject* gameobj,PyTypeObject* T ); + SCA_ILogicBrick(SCA_IObject* gameobj); virtual ~SCA_ILogicBrick(); void SetExecutePriority(int execute_Priority); @@ -121,10 +121,6 @@ public: } virtual bool LessComparedTo(SCA_ILogicBrick* other); - - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); static class SCA_LogicManager* m_sCurrentLogicManager; diff --git a/source/gameengine/GameLogic/SCA_IObject.cpp b/source/gameengine/GameLogic/SCA_IObject.cpp index 9876f2512c0..6cd11f9e553 100644 --- a/source/gameengine/GameLogic/SCA_IObject.cpp +++ b/source/gameengine/GameLogic/SCA_IObject.cpp @@ -41,8 +41,11 @@ MT_Point3 SCA_IObject::m_sDummy=MT_Point3(0,0,0); SG_QList SCA_IObject::m_activeBookmarkedControllers; -SCA_IObject::SCA_IObject(PyTypeObject* T): CValue(T), m_initState(0), m_state(0), m_firstState(NULL) - +SCA_IObject::SCA_IObject(): + CValue(), + m_initState(0), + m_state(0), + m_firstState(NULL) { m_suspended = false; } @@ -218,51 +221,6 @@ SCA_IActuator* SCA_IObject::FindActuator(const STR_String& actuatorname) } - -#if 0 -const MT_Point3& SCA_IObject::ConvertPythonPylist(PyObject* pylist) -{ - bool error = false; - m_sDummy = MT_Vector3(0,0,0); - if (pylist->ob_type == &CListValue::Type) - { - CListValue* listval = (CListValue*) pylist; - int numelem = listval->GetCount(); - if ( numelem <= 3) - { - int index; - for (index = 0;indexGetValue(index)->GetNumber(); - } - } else - { - error = true; - } - - } else - { - - // assert the list is long enough... - int numitems = PyList_Size(pylist); - if (numitems <= 3) - { - int index; - for (index=0;indexIsTriggered(this); - return PyInt_FromLong(retval); + return PyLong_FromSsize_t(retval); } /** @@ -355,7 +354,7 @@ const char SCA_ISensor::GetFrequency_doc[] = PyObject* SCA_ISensor::PyGetFrequency() { ShowDeprecationWarning("getFrequency()", "the frequency property"); - return PyInt_FromLong(m_pulse_frequency); + return PyLong_FromSsize_t(m_pulse_frequency); } /** @@ -489,19 +488,17 @@ PyTypeObject SCA_ISensor::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, + &SCA_ILogicBrick::Type, + 0,0,0,0,0,0, + py_base_new }; -PyParentObject SCA_ISensor::Parents[] = { - &SCA_ISensor::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL -}; PyMethodDef SCA_ISensor::Methods[] = { //Deprecated functions -----> {"isPositive", (PyCFunction) SCA_ISensor::sPyIsPositive, @@ -548,19 +545,6 @@ PyAttributeDef SCA_ISensor::Attributes[] = { { NULL } //Sentinel }; -PyObject* SCA_ISensor::py_getattro(PyObject *attr) -{ - py_getattro_up(SCA_ILogicBrick); -} - -PyObject* SCA_ISensor::py_getattro_dict() { - py_getattro_dict_up(SCA_ILogicBrick); -} - -int SCA_ISensor::py_setattro(PyObject *attr, PyObject *value) -{ - py_setattro_up(SCA_ILogicBrick); -} PyObject* SCA_ISensor::pyattr_get_triggered(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { @@ -568,13 +552,13 @@ PyObject* SCA_ISensor::pyattr_get_triggered(void *self_v, const KX_PYATTRIBUTE_D int retval = 0; if (SCA_PythonController::m_sCurrentController) retval = SCA_PythonController::m_sCurrentController->IsTriggered(self); - return PyInt_FromLong(retval); + return PyLong_FromSsize_t(retval); } PyObject* SCA_ISensor::pyattr_get_positive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { SCA_ISensor* self= static_cast(self_v); - return PyInt_FromLong(self->GetState()); + return PyLong_FromSsize_t(self->GetState()); } int SCA_ISensor::pyattr_check_level(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) diff --git a/source/gameengine/GameLogic/SCA_ISensor.h b/source/gameengine/GameLogic/SCA_ISensor.h index 9bbd6ed41e4..81864ab6a34 100644 --- a/source/gameengine/GameLogic/SCA_ISensor.h +++ b/source/gameengine/GameLogic/SCA_ISensor.h @@ -101,8 +101,7 @@ public: }; SCA_ISensor(SCA_IObject* gameobj, - class SCA_EventManager* eventmgr, - PyTypeObject* T );; + class SCA_EventManager* eventmgr);; ~SCA_ISensor(); virtual void ReParent(SCA_IObject* parent); @@ -173,10 +172,6 @@ public: { return !m_links; } /* Python functions: */ - - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); //Deprecated functions -----> KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,IsPositive); diff --git a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp index 336529667d7..f55921e648b 100644 --- a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp +++ b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp @@ -46,9 +46,8 @@ SCA_JoystickSensor::SCA_JoystickSensor(class SCA_JoystickManager* eventmgr, short int joymode, int axis, int axisf,int prec, int button, - int hat, int hatf, bool allevents, - PyTypeObject* T ) - :SCA_ISensor(gameobj,eventmgr,T), + int hat, int hatf, bool allevents) + :SCA_ISensor(gameobj,eventmgr), m_pJoystickMgr(eventmgr), m_axis(axis), m_axisf(axisf), @@ -269,23 +268,17 @@ PyTypeObject SCA_JoystickSensor::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - - -PyParentObject SCA_JoystickSensor::Parents[] = { - &SCA_JoystickSensor::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_ISensor::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; - PyMethodDef SCA_JoystickSensor::Methods[] = { //Deprecated functions ------> {"getIndex", (PyCFunction) SCA_JoystickSensor::sPyGetIndex, METH_NOARGS, (PY_METHODCHAR)GetIndex_doc}, @@ -328,20 +321,6 @@ PyAttributeDef SCA_JoystickSensor::Attributes[] = { { NULL } //Sentinel }; -PyObject* SCA_JoystickSensor::py_getattro(PyObject *attr) -{ - py_getattro_up(SCA_ISensor); -} - -PyObject* SCA_JoystickSensor::py_getattro_dict() { - py_getattro_dict_up(SCA_ISensor); -} - -int SCA_JoystickSensor::py_setattro(PyObject *attr, PyObject *value) -{ - py_setattro_up(SCA_ISensor); -} - /* get index ---------------------------------------------------------- */ const char SCA_JoystickSensor::GetIndex_doc[] = @@ -349,7 +328,7 @@ const char SCA_JoystickSensor::GetIndex_doc[] = "\tReturns the joystick index to use.\n"; PyObject* SCA_JoystickSensor::PyGetIndex( ) { ShowDeprecationWarning("getIndex()", "the index property"); - return PyInt_FromLong(m_joyindex); + return PyLong_FromSsize_t(m_joyindex); } @@ -359,7 +338,7 @@ const char SCA_JoystickSensor::SetIndex_doc[] = "\tSets the joystick index to use.\n"; PyObject* SCA_JoystickSensor::PySetIndex( PyObject* value ) { ShowDeprecationWarning("setIndex()", "the index property"); - int index = PyInt_AsLong( value ); /* -1 on error, will raise an error in this case */ + int index = PyLong_AsSsize_t( value ); /* -1 on error, will raise an error in this case */ if (index < 0 || index >= JOYINDEX_MAX) { PyErr_SetString(PyExc_ValueError, "joystick index out of range or not an int"); return NULL; @@ -410,7 +389,7 @@ PyObject* SCA_JoystickSensor::PyGetAxisValue( ) { PyObject *list= PyList_New(axis_index); while(axis_index--) { - PyList_SET_ITEM(list, axis_index, PyInt_FromLong(joy->GetAxisPosition(axis_index))); + PyList_SET_ITEM(list, axis_index, PyLong_FromSsize_t(joy->GetAxisPosition(axis_index))); } return list; @@ -423,7 +402,7 @@ const char SCA_JoystickSensor::GetThreshold_doc[] = "\tReturns the threshold of the axis.\n"; PyObject* SCA_JoystickSensor::PyGetThreshold( ) { ShowDeprecationWarning("getThreshold()", "the threshold property"); - return PyInt_FromLong(m_precision); + return PyLong_FromSsize_t(m_precision); } @@ -447,7 +426,7 @@ const char SCA_JoystickSensor::GetButton_doc[] = "\tReturns the current button this sensor is checking.\n"; PyObject* SCA_JoystickSensor::PyGetButton( ) { ShowDeprecationWarning("getButton()", "the button property"); - return PyInt_FromLong(m_button); + return PyLong_FromSsize_t(m_button); } /* set button -------------------------------------------------------- */ @@ -456,7 +435,7 @@ const char SCA_JoystickSensor::SetButton_doc[] = "\tSets the button the sensor reacts to.\n"; PyObject* SCA_JoystickSensor::PySetButton( PyObject* value ) { ShowDeprecationWarning("setButton()", "the button property"); - int button = PyInt_AsLong(value); + int button = PyLong_AsSsize_t(value); if(button==-1 && PyErr_Occurred()) { PyErr_SetString(PyExc_ValueError, "expected an int"); return NULL; @@ -487,7 +466,7 @@ PyObject* SCA_JoystickSensor::PyGetButtonActiveList( ) { if(joy) { for (i=0; i < joy->GetNumberOfButtons(); i++) { if (joy->aButtonPressIsPositive(i)) { - value = PyInt_FromLong(i); + value = PyLong_FromSsize_t(i); PyList_Append(ls, value); Py_DECREF(value); } @@ -549,7 +528,7 @@ PyObject* SCA_JoystickSensor::PyNumberOfAxes( ) { ShowDeprecationWarning("getNumAxes()", "the numAxis property"); SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); // when the joystick is null their is 0 exis still. dumb but scripters should use isConnected() - return PyInt_FromLong( joy ? joy->GetNumberOfAxes() : 0 ); + return PyLong_FromSsize_t( joy ? joy->GetNumberOfAxes() : 0 ); } @@ -559,7 +538,7 @@ const char SCA_JoystickSensor::NumberOfButtons_doc[] = PyObject* SCA_JoystickSensor::PyNumberOfButtons( ) { ShowDeprecationWarning("getNumButtons()", "the numButtons property"); SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); - return PyInt_FromLong( joy ? joy->GetNumberOfButtons() : 0 ); + return PyLong_FromSsize_t( joy ? joy->GetNumberOfButtons() : 0 ); } @@ -569,7 +548,7 @@ const char SCA_JoystickSensor::NumberOfHats_doc[] = PyObject* SCA_JoystickSensor::PyNumberOfHats( ) { ShowDeprecationWarning("getNumHats()", "the numHats property"); SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); - return PyInt_FromLong( joy ? joy->GetNumberOfHats() : 0 ); + return PyLong_FromSsize_t( joy ? joy->GetNumberOfHats() : 0 ); } const char SCA_JoystickSensor::Connected_doc[] = @@ -591,7 +570,7 @@ PyObject* SCA_JoystickSensor::pyattr_get_axis_values(void *self_v, const KX_PYAT PyObject *list= PyList_New(axis_index); while(axis_index--) { - PyList_SET_ITEM(list, axis_index, PyInt_FromLong(joy->GetAxisPosition(axis_index))); + PyList_SET_ITEM(list, axis_index, PyLong_FromSsize_t(joy->GetAxisPosition(axis_index))); } return list; @@ -607,7 +586,7 @@ PyObject* SCA_JoystickSensor::pyattr_get_axis_single(void *self_v, const KX_PYAT return NULL; } - return PyInt_FromLong(joy->GetAxisPosition(self->m_axis-1)); + return PyLong_FromSsize_t(joy->GetAxisPosition(self->m_axis-1)); } PyObject* SCA_JoystickSensor::pyattr_get_hat_values(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) @@ -619,7 +598,7 @@ PyObject* SCA_JoystickSensor::pyattr_get_hat_values(void *self_v, const KX_PYATT PyObject *list= PyList_New(hat_index); while(hat_index--) { - PyList_SET_ITEM(list, hat_index, PyInt_FromLong(joy->GetHat(hat_index))); + PyList_SET_ITEM(list, hat_index, PyLong_FromSsize_t(joy->GetHat(hat_index))); } return list; @@ -630,28 +609,28 @@ PyObject* SCA_JoystickSensor::pyattr_get_hat_single(void *self_v, const KX_PYATT SCA_JoystickSensor* self= static_cast(self_v); SCA_Joystick *joy = self->m_pJoystickMgr->GetJoystickDevice(self->m_joyindex); - return PyInt_FromLong(joy->GetHat(self->m_hat-1)); + return PyLong_FromSsize_t(joy->GetHat(self->m_hat-1)); } PyObject* SCA_JoystickSensor::pyattr_get_num_axis(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { SCA_JoystickSensor* self= static_cast(self_v); SCA_Joystick *joy = self->m_pJoystickMgr->GetJoystickDevice(self->m_joyindex); - return PyInt_FromLong( joy ? joy->GetNumberOfAxes() : 0 ); + return PyLong_FromSsize_t( joy ? joy->GetNumberOfAxes() : 0 ); } PyObject* SCA_JoystickSensor::pyattr_get_num_buttons(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { SCA_JoystickSensor* self= static_cast(self_v); SCA_Joystick *joy = self->m_pJoystickMgr->GetJoystickDevice(self->m_joyindex); - return PyInt_FromLong( joy ? joy->GetNumberOfButtons() : 0 ); + return PyLong_FromSsize_t( joy ? joy->GetNumberOfButtons() : 0 ); } PyObject* SCA_JoystickSensor::pyattr_get_num_hats(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { SCA_JoystickSensor* self= static_cast(self_v); SCA_Joystick *joy = self->m_pJoystickMgr->GetJoystickDevice(self->m_joyindex); - return PyInt_FromLong( joy ? joy->GetNumberOfHats() : 0 ); + return PyLong_FromSsize_t( joy ? joy->GetNumberOfHats() : 0 ); } PyObject* SCA_JoystickSensor::pyattr_get_connected(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) diff --git a/source/gameengine/GameLogic/SCA_JoystickSensor.h b/source/gameengine/GameLogic/SCA_JoystickSensor.h index e6a1d2eef32..32f8ce567d2 100644 --- a/source/gameengine/GameLogic/SCA_JoystickSensor.h +++ b/source/gameengine/GameLogic/SCA_JoystickSensor.h @@ -106,8 +106,7 @@ public: short int joymode, int axis, int axisf,int prec, int button, - int hat, int hatf, bool allevents, - PyTypeObject* T=&Type ); + int hat, int hatf, bool allevents); virtual ~SCA_JoystickSensor(); virtual CValue* GetReplica(); @@ -123,10 +122,6 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); - /* Joystick Index */ KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,GetIndex); KX_PYMETHOD_DOC_O(SCA_JoystickSensor,SetIndex); diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp index f8ee8ed8b41..999e34dfa36 100644 --- a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp +++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp @@ -48,9 +48,8 @@ SCA_KeyboardSensor::SCA_KeyboardSensor(SCA_KeyboardManager* keybdmgr, bool bAllKeys, const STR_String& targetProp, const STR_String& toggleProp, - SCA_IObject* gameobj, - PyTypeObject* T ) - :SCA_ISensor(gameobj,keybdmgr,T), + SCA_IObject* gameobj) + :SCA_ISensor(gameobj,keybdmgr), m_pKeyboardMgr(keybdmgr), m_hotkey(hotkey), m_qual(qual), @@ -418,7 +417,7 @@ const char SCA_KeyboardSensor::GetKey_doc[] = PyObject* SCA_KeyboardSensor::PyGetKey() { ShowDeprecationWarning("getKey()", "the key property"); - return PyInt_FromLong(m_hotkey); + return PyLong_FromSsize_t(m_hotkey); } /** 2. SetKey: change the key to look at */ @@ -450,7 +449,7 @@ const char SCA_KeyboardSensor::GetHold1_doc[] = PyObject* SCA_KeyboardSensor::PyGetHold1() { ShowDeprecationWarning("getHold1()", "the hold1 property"); - return PyInt_FromLong(m_qual); + return PyLong_FromSsize_t(m_qual); } /** 4. SetHold1: change the first bucky bit */ @@ -482,7 +481,7 @@ const char SCA_KeyboardSensor::GetHold2_doc[] = PyObject* SCA_KeyboardSensor::PyGetHold2() { ShowDeprecationWarning("getHold2()", "the hold2 property"); - return PyInt_FromLong(m_qual2); + return PyLong_FromSsize_t(m_qual2); } /** 6. SetHold2: change the second bucky bit */ @@ -532,8 +531,8 @@ PyObject* SCA_KeyboardSensor::PyGetPressedKeys() || (inevent.m_status == SCA_InputEvent::KX_JUSTRELEASED)) { PyObject* keypair = PyList_New(2); - PyList_SET_ITEM(keypair,0,PyInt_FromLong(i)); - PyList_SET_ITEM(keypair,1,PyInt_FromLong(inevent.m_status)); + PyList_SET_ITEM(keypair,0,PyLong_FromSsize_t(i)); + PyList_SET_ITEM(keypair,1,PyLong_FromSsize_t(inevent.m_status)); PyList_SET_ITEM(resultlist,index,keypair); index++; @@ -572,8 +571,8 @@ PyObject* SCA_KeyboardSensor::PyGetCurrentlyPressedKeys() || (inevent.m_status == SCA_InputEvent::KX_JUSTACTIVATED)) { PyObject* keypair = PyList_New(2); - PyList_SET_ITEM(keypair,0,PyInt_FromLong(i)); - PyList_SET_ITEM(keypair,1,PyInt_FromLong(inevent.m_status)); + PyList_SET_ITEM(keypair,0,PyLong_FromSsize_t(i)); + PyList_SET_ITEM(keypair,1,PyLong_FromSsize_t(inevent.m_status)); PyList_SET_ITEM(resultlist,index,keypair); index++; @@ -592,12 +591,12 @@ KX_PYMETHODDEF_DOC_O(SCA_KeyboardSensor, getKeyStatus, "getKeyStatus(keycode)\n" "\tGet the given key's status (KX_NO_INPUTSTATUS, KX_JUSTACTIVATED, KX_ACTIVE or KX_JUSTRELEASED).\n") { - if (!PyInt_Check(value)) { + if (!PyLong_Check(value)) { PyErr_SetString(PyExc_ValueError, "sensor.getKeyStatus(int): Keyboard Sensor, expected an int"); return NULL; } - int keycode = PyInt_AsLong(value); + int keycode = PyLong_AsSsize_t(value); if ((keycode < SCA_IInputDevice::KX_BEGINKEY) || (keycode > SCA_IInputDevice::KX_ENDKEY)){ @@ -607,7 +606,7 @@ KX_PYMETHODDEF_DOC_O(SCA_KeyboardSensor, getKeyStatus, SCA_IInputDevice* inputdev = m_pKeyboardMgr->GetInputDevice(); const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) keycode); - return PyInt_FromLong(inevent.m_status); + return PyLong_FromSsize_t(inevent.m_status); } /* ------------------------------------------------------------------------- */ @@ -631,19 +630,15 @@ PyTypeObject SCA_KeyboardSensor::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject SCA_KeyboardSensor::Parents[] = { - &SCA_KeyboardSensor::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_ISensor::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef SCA_KeyboardSensor::Methods[] = { @@ -672,20 +667,6 @@ PyAttributeDef SCA_KeyboardSensor::Attributes[] = { { NULL } //Sentinel }; -PyObject* SCA_KeyboardSensor::py_getattro(PyObject *attr) -{ - py_getattro_up(SCA_ISensor); -} - -PyObject* SCA_KeyboardSensor::py_getattro_dict() { - py_getattro_dict_up(SCA_ISensor); -} - -int SCA_KeyboardSensor::py_setattro(PyObject *attr, PyObject *value) -{ - py_setattro_up(SCA_ISensor); -} - PyObject* SCA_KeyboardSensor::pyattr_get_events(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { @@ -701,8 +682,8 @@ PyObject* SCA_KeyboardSensor::pyattr_get_events(void *self_v, const KX_PYATTRIBU if (inevent.m_status != SCA_InputEvent::KX_NO_INPUTSTATUS) { PyObject* keypair = PyList_New(2); - PyList_SET_ITEM(keypair,0,PyInt_FromLong(i)); - PyList_SET_ITEM(keypair,1,PyInt_FromLong(inevent.m_status)); + PyList_SET_ITEM(keypair,0,PyLong_FromSsize_t(i)); + PyList_SET_ITEM(keypair,1,PyLong_FromSsize_t(inevent.m_status)); PyList_Append(resultlist,keypair); } } diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.h b/source/gameengine/GameLogic/SCA_KeyboardSensor.h index 033225cd9be..3185b386d41 100644 --- a/source/gameengine/GameLogic/SCA_KeyboardSensor.h +++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.h @@ -94,8 +94,7 @@ public: bool bAllKeys, const STR_String& targetProp, const STR_String& toggleProp, - SCA_IObject* gameobj, - PyTypeObject* T=&Type ); + SCA_IObject* gameobj); virtual ~SCA_KeyboardSensor(); virtual CValue* GetReplica(); virtual void Init(); @@ -110,10 +109,6 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); - //Deprecated functions -----> /** 1. GetKey : check which key this sensor looks at */ KX_PYMETHOD_DOC_NOARGS(SCA_KeyboardSensor,GetKey); diff --git a/source/gameengine/GameLogic/SCA_LogicManager.cpp b/source/gameengine/GameLogic/SCA_LogicManager.cpp index 83271288154..b782c6dfb93 100644 --- a/source/gameengine/GameLogic/SCA_LogicManager.cpp +++ b/source/gameengine/GameLogic/SCA_LogicManager.cpp @@ -307,6 +307,7 @@ void SCA_LogicManager::AddTriggeredController(SCA_IController* controller, SCA_I controller->Activate(m_triggeredControllerSet); // so that the controller knows which sensor has activited it // only needed for python controller + // Note that this is safe even if the controller is subclassed. if (controller->GetType() == &SCA_PythonController::Type) { SCA_PythonController* pythonController = (SCA_PythonController*)controller; diff --git a/source/gameengine/GameLogic/SCA_MouseSensor.cpp b/source/gameengine/GameLogic/SCA_MouseSensor.cpp index c5e1c3c0441..49fa19dce38 100644 --- a/source/gameengine/GameLogic/SCA_MouseSensor.cpp +++ b/source/gameengine/GameLogic/SCA_MouseSensor.cpp @@ -49,9 +49,8 @@ SCA_MouseSensor::SCA_MouseSensor(SCA_MouseManager* eventmgr, int startx,int starty, short int mousemode, - SCA_IObject* gameobj, - PyTypeObject* T) - : SCA_ISensor(gameobj,eventmgr, T), + SCA_IObject* gameobj) + : SCA_ISensor(gameobj,eventmgr), m_pMouseMgr(eventmgr), m_x(startx), m_y(starty) @@ -254,7 +253,7 @@ const char SCA_MouseSensor::GetXPosition_doc[] = "\tpixels\n"; PyObject* SCA_MouseSensor::PyGetXPosition() { ShowDeprecationWarning("getXPosition()", "the position property"); - return PyInt_FromLong(m_x); + return PyLong_FromSsize_t(m_x); } /* get y position ---------------------------------------------------------- */ @@ -265,7 +264,7 @@ const char SCA_MouseSensor::GetYPosition_doc[] = "\tpixels\n"; PyObject* SCA_MouseSensor::PyGetYPosition() { ShowDeprecationWarning("getYPosition()", "the position property"); - return PyInt_FromLong(m_y); + return PyLong_FromSsize_t(m_y); } //<----- Deprecated @@ -273,9 +272,9 @@ KX_PYMETHODDEF_DOC_O(SCA_MouseSensor, getButtonStatus, "getButtonStatus(button)\n" "\tGet the given button's status (KX_INPUT_NONE, KX_INPUT_NONE, KX_INPUT_JUST_ACTIVATED, KX_INPUT_ACTIVE, KX_INPUT_JUST_RELEASED).\n") { - if (PyInt_Check(value)) + if (PyLong_Check(value)) { - int button = PyInt_AsLong(value); + int button = PyLong_AsSsize_t(value); if ((button < SCA_IInputDevice::KX_LEFTMOUSE) || (button > SCA_IInputDevice::KX_RIGHTMOUSE)){ @@ -285,7 +284,7 @@ KX_PYMETHODDEF_DOC_O(SCA_MouseSensor, getButtonStatus, SCA_IInputDevice* mousedev = m_pMouseMgr->GetInputDevice(); const SCA_InputEvent& event = mousedev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) button); - return PyInt_FromLong(event.m_status); + return PyLong_FromSsize_t(event.m_status); } Py_RETURN_NONE; @@ -312,19 +311,15 @@ PyTypeObject SCA_MouseSensor::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject SCA_MouseSensor::Parents[] = { - &SCA_MouseSensor::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_ISensor::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef SCA_MouseSensor::Methods[] = { @@ -342,18 +337,4 @@ PyAttributeDef SCA_MouseSensor::Attributes[] = { { NULL } //Sentinel }; -PyObject* SCA_MouseSensor::py_getattro(PyObject *attr) -{ - py_getattro_up(SCA_ISensor); -} - -PyObject* SCA_MouseSensor::py_getattro_dict() { - py_getattro_dict_up(SCA_ISensor); -} - -int SCA_MouseSensor::py_setattro(PyObject *attr, PyObject *value) -{ - py_setattro_up(SCA_ISensor); -} - /* eof */ diff --git a/source/gameengine/GameLogic/SCA_MouseSensor.h b/source/gameengine/GameLogic/SCA_MouseSensor.h index 6d6302b514a..47f0378bf69 100644 --- a/source/gameengine/GameLogic/SCA_MouseSensor.h +++ b/source/gameengine/GameLogic/SCA_MouseSensor.h @@ -92,8 +92,7 @@ class SCA_MouseSensor : public SCA_ISensor SCA_MouseSensor(class SCA_MouseManager* keybdmgr, int startx,int starty, short int mousemode, - SCA_IObject* gameobj, - PyTypeObject* T=&Type ); + SCA_IObject* gameobj); virtual ~SCA_MouseSensor(); virtual CValue* GetReplica(); @@ -109,10 +108,6 @@ class SCA_MouseSensor : public SCA_ISensor /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); - //Deprecated functions -----> /* read x-coordinate */ KX_PYMETHOD_DOC_NOARGS(SCA_MouseSensor,GetXPosition); diff --git a/source/gameengine/GameLogic/SCA_NANDController.cpp b/source/gameengine/GameLogic/SCA_NANDController.cpp index d27aea5e6f7..c00e5d6e617 100644 --- a/source/gameengine/GameLogic/SCA_NANDController.cpp +++ b/source/gameengine/GameLogic/SCA_NANDController.cpp @@ -42,10 +42,9 @@ /* Native functions */ /* ------------------------------------------------------------------------- */ -SCA_NANDController::SCA_NANDController(SCA_IObject* gameobj, - PyTypeObject* T) +SCA_NANDController::SCA_NANDController(SCA_IObject* gameobj) : - SCA_IController(gameobj,T) + SCA_IController(gameobj) { } @@ -116,19 +115,15 @@ PyTypeObject SCA_NANDController::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject SCA_NANDController::Parents[] = { - &SCA_NANDController::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IController::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef SCA_NANDController::Methods[] = { @@ -139,12 +134,4 @@ PyAttributeDef SCA_NANDController::Attributes[] = { { NULL } //Sentinel }; -PyObject* SCA_NANDController::py_getattro(PyObject *attr) { - py_getattro_up(SCA_IController); -} - -PyObject* SCA_NANDController::py_getattro_dict() { - py_getattro_dict_up(SCA_IController); -} - /* eof */ diff --git a/source/gameengine/GameLogic/SCA_NANDController.h b/source/gameengine/GameLogic/SCA_NANDController.h index 0ae0ff19745..36a145e5f2b 100644 --- a/source/gameengine/GameLogic/SCA_NANDController.h +++ b/source/gameengine/GameLogic/SCA_NANDController.h @@ -39,7 +39,7 @@ class SCA_NANDController : public SCA_IController Py_Header; //virtual void Trigger(class SCA_LogicManager* logicmgr); public: - SCA_NANDController(SCA_IObject* gameobj,PyTypeObject* T=&Type); + SCA_NANDController(SCA_IObject* gameobj); virtual ~SCA_NANDController(); virtual CValue* GetReplica(); virtual void Trigger(SCA_LogicManager* logicmgr); @@ -47,10 +47,6 @@ public: /* --------------------------------------------------------------------- */ /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - }; #endif //__KX_NANDCONTROLLER diff --git a/source/gameengine/GameLogic/SCA_NORController.cpp b/source/gameengine/GameLogic/SCA_NORController.cpp index 6c9141636b2..9762d44fd5d 100644 --- a/source/gameengine/GameLogic/SCA_NORController.cpp +++ b/source/gameengine/GameLogic/SCA_NORController.cpp @@ -42,10 +42,9 @@ /* Native functions */ /* ------------------------------------------------------------------------- */ -SCA_NORController::SCA_NORController(SCA_IObject* gameobj, - PyTypeObject* T) +SCA_NORController::SCA_NORController(SCA_IObject* gameobj) : - SCA_IController(gameobj,T) + SCA_IController(gameobj) { } @@ -116,19 +115,15 @@ PyTypeObject SCA_NORController::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject SCA_NORController::Parents[] = { - &SCA_NORController::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IController::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef SCA_NORController::Methods[] = { @@ -139,12 +134,4 @@ PyAttributeDef SCA_NORController::Attributes[] = { { NULL } //Sentinel }; -PyObject* SCA_NORController::py_getattro(PyObject *attr) { - py_getattro_up(SCA_IController); -} - -PyObject* SCA_NORController::py_getattro_dict() { - py_getattro_dict_up(SCA_IController); -} - /* eof */ diff --git a/source/gameengine/GameLogic/SCA_NORController.h b/source/gameengine/GameLogic/SCA_NORController.h index 06cbb70a489..b96232375d6 100644 --- a/source/gameengine/GameLogic/SCA_NORController.h +++ b/source/gameengine/GameLogic/SCA_NORController.h @@ -39,18 +39,10 @@ class SCA_NORController : public SCA_IController Py_Header; //virtual void Trigger(class SCA_LogicManager* logicmgr); public: - SCA_NORController(SCA_IObject* gameobj,PyTypeObject* T=&Type); + SCA_NORController(SCA_IObject* gameobj); virtual ~SCA_NORController(); virtual CValue* GetReplica(); virtual void Trigger(SCA_LogicManager* logicmgr); - - /* --------------------------------------------------------------------- */ - /* Python interface ---------------------------------------------------- */ - /* --------------------------------------------------------------------- */ - - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - }; #endif //__KX_NORCONTROLLER diff --git a/source/gameengine/GameLogic/SCA_ORController.cpp b/source/gameengine/GameLogic/SCA_ORController.cpp index 42c0a67d657..a526dd8353c 100644 --- a/source/gameengine/GameLogic/SCA_ORController.cpp +++ b/source/gameengine/GameLogic/SCA_ORController.cpp @@ -42,9 +42,8 @@ /* Native functions */ /* ------------------------------------------------------------------------- */ -SCA_ORController::SCA_ORController(SCA_IObject* gameobj, - PyTypeObject* T) - :SCA_IController(gameobj, T) +SCA_ORController::SCA_ORController(SCA_IObject* gameobj) + :SCA_IController(gameobj) { } @@ -110,19 +109,15 @@ PyTypeObject SCA_ORController::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject SCA_ORController::Parents[] = { - &SCA_ORController::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IController::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef SCA_ORController::Methods[] = { @@ -133,13 +128,4 @@ PyAttributeDef SCA_ORController::Attributes[] = { { NULL } //Sentinel }; - -PyObject* SCA_ORController::py_getattro(PyObject *attr) { - py_getattro_up(SCA_IController); -} - -PyObject* SCA_ORController::py_getattro_dict() { - py_getattro_dict_up(SCA_IController); -} - /* eof */ diff --git a/source/gameengine/GameLogic/SCA_ORController.h b/source/gameengine/GameLogic/SCA_ORController.h index 66f772c739e..09d31a85190 100644 --- a/source/gameengine/GameLogic/SCA_ORController.h +++ b/source/gameengine/GameLogic/SCA_ORController.h @@ -39,18 +39,11 @@ class SCA_ORController : public SCA_IController Py_Header; //virtual void Trigger(class SCA_LogicManager* logicmgr); public: - SCA_ORController(SCA_IObject* gameobj, PyTypeObject* T=&Type); + SCA_ORController(SCA_IObject* gameobj); virtual ~SCA_ORController(); virtual CValue* GetReplica(); virtual void Trigger(SCA_LogicManager* logicmgr); - - /* --------------------------------------------------------------------- */ - /* Python interface ---------------------------------------------------- */ - /* --------------------------------------------------------------------- */ - - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); }; #endif //__KX_ORCONTROLLER diff --git a/source/gameengine/GameLogic/SCA_PropertyActuator.cpp b/source/gameengine/GameLogic/SCA_PropertyActuator.cpp index 4faa4b55d4a..215e30eceaf 100644 --- a/source/gameengine/GameLogic/SCA_PropertyActuator.cpp +++ b/source/gameengine/GameLogic/SCA_PropertyActuator.cpp @@ -42,8 +42,8 @@ /* Native functions */ /* ------------------------------------------------------------------------- */ -SCA_PropertyActuator::SCA_PropertyActuator(SCA_IObject* gameobj,SCA_IObject* sourceObj,const STR_String& propname,const STR_String& expr,int acttype,PyTypeObject* T ) - : SCA_IActuator(gameobj,T), +SCA_PropertyActuator::SCA_PropertyActuator(SCA_IObject* gameobj,SCA_IObject* sourceObj,const STR_String& propname,const STR_String& expr,int acttype) + : SCA_IActuator(gameobj), m_type(acttype), m_propname(propname), m_exprtxt(expr), @@ -244,19 +244,15 @@ PyTypeObject SCA_PropertyActuator::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject SCA_PropertyActuator::Parents[] = { - &SCA_PropertyActuator::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IActuator::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef SCA_PropertyActuator::Methods[] = { @@ -276,18 +272,6 @@ PyAttributeDef SCA_PropertyActuator::Attributes[] = { { NULL } //Sentinel }; -PyObject* SCA_PropertyActuator::py_getattro(PyObject *attr) { - py_getattro_up(SCA_IActuator); -} - -PyObject* SCA_PropertyActuator::py_getattro_dict() { - py_getattro_dict_up(SCA_IActuator); -} - -int SCA_PropertyActuator::py_setattro(PyObject *attr, PyObject *value) { - py_setattro_up(SCA_IActuator); -} - /* 1. setProperty */ const char SCA_PropertyActuator::SetProperty_doc[] = "setProperty(name)\n" @@ -322,7 +306,7 @@ const char SCA_PropertyActuator::GetProperty_doc[] = PyObject* SCA_PropertyActuator::PyGetProperty(PyObject* args, PyObject* kwds) { ShowDeprecationWarning("getProperty()", "the 'propName' property"); - return PyString_FromString(m_propname); + return PyUnicode_FromString(m_propname); } /* 3. setValue */ @@ -352,7 +336,7 @@ const char SCA_PropertyActuator::GetValue_doc[] = PyObject* SCA_PropertyActuator::PyGetValue(PyObject* args, PyObject* kwds) { ShowDeprecationWarning("getValue()", "the value property"); - return PyString_FromString(m_exprtxt); + return PyUnicode_FromString(m_exprtxt); } /* eof */ diff --git a/source/gameengine/GameLogic/SCA_PropertyActuator.h b/source/gameengine/GameLogic/SCA_PropertyActuator.h index a8df08dfc6e..8fb2e7a7bc5 100644 --- a/source/gameengine/GameLogic/SCA_PropertyActuator.h +++ b/source/gameengine/GameLogic/SCA_PropertyActuator.h @@ -64,9 +64,7 @@ public: SCA_IObject* sourceObj, const STR_String& propname, const STR_String& expr, - int acttype, - PyTypeObject* T=&Type - ); + int acttype); ~SCA_PropertyActuator(); @@ -86,10 +84,6 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); - // python wrapped methods KX_PYMETHOD_DOC(SCA_PropertyActuator,SetProperty); KX_PYMETHOD_DOC(SCA_PropertyActuator,GetProperty); diff --git a/source/gameengine/GameLogic/SCA_PropertySensor.cpp b/source/gameengine/GameLogic/SCA_PropertySensor.cpp index 3b343af3cba..6d2e1a0aca5 100644 --- a/source/gameengine/GameLogic/SCA_PropertySensor.cpp +++ b/source/gameengine/GameLogic/SCA_PropertySensor.cpp @@ -48,9 +48,8 @@ SCA_PropertySensor::SCA_PropertySensor(SCA_EventManager* eventmgr, const STR_String& propname, const STR_String& propval, const STR_String& propmaxval, - KX_PROPSENSOR_TYPE checktype, - PyTypeObject* T ) - : SCA_ISensor(gameobj,eventmgr,T), + KX_PROPSENSOR_TYPE checktype) + : SCA_ISensor(gameobj,eventmgr), m_checktype(checktype), m_checkpropval(propval), m_checkpropmaxval(propmaxval), @@ -319,19 +318,15 @@ PyTypeObject SCA_PropertySensor::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject SCA_PropertySensor::Parents[] = { - &SCA_PropertySensor::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_ISensor::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef SCA_PropertySensor::Methods[] = { @@ -353,19 +348,6 @@ PyAttributeDef SCA_PropertySensor::Attributes[] = { { NULL } //Sentinel }; - -PyObject* SCA_PropertySensor::py_getattro(PyObject *attr) { - py_getattro_up(SCA_ISensor); -} - -PyObject* SCA_PropertySensor::py_getattro_dict() { - py_getattro_dict_up(SCA_ISensor); -} - -int SCA_PropertySensor::py_setattro(PyObject *attr, PyObject *value) { - py_setattro_up(SCA_ISensor); -} - /* 1. getType */ const char SCA_PropertySensor::GetType_doc[] = "getType()\n" @@ -373,7 +355,7 @@ const char SCA_PropertySensor::GetType_doc[] = PyObject* SCA_PropertySensor::PyGetType() { ShowDeprecationWarning("getType()", "the mode property"); - return PyInt_FromLong(m_checktype); + return PyLong_FromSsize_t(m_checktype); } /* 2. setType */ @@ -407,7 +389,7 @@ const char SCA_PropertySensor::GetProperty_doc[] = PyObject* SCA_PropertySensor::PyGetProperty() { ShowDeprecationWarning("getProperty()", "the 'propName' property"); - return PyString_FromString(m_checkpropname); + return PyUnicode_FromString(m_checkpropname); } /* 4. setProperty */ @@ -444,7 +426,7 @@ const char SCA_PropertySensor::GetValue_doc[] = PyObject* SCA_PropertySensor::PyGetValue() { ShowDeprecationWarning("getValue()", "the value property"); - return PyString_FromString(m_checkpropval); + return PyUnicode_FromString(m_checkpropval); } /* 6. setValue */ diff --git a/source/gameengine/GameLogic/SCA_PropertySensor.h b/source/gameengine/GameLogic/SCA_PropertySensor.h index 538ecd65949..3513fcdf5ae 100644 --- a/source/gameengine/GameLogic/SCA_PropertySensor.h +++ b/source/gameengine/GameLogic/SCA_PropertySensor.h @@ -67,8 +67,7 @@ public: const STR_String& propname, const STR_String& propval, const STR_String& propmaxval, - KX_PROPSENSOR_TYPE checktype, - PyTypeObject* T=&Type ); + KX_PROPSENSOR_TYPE checktype); /** * For property sensor, it is used to release the pre-calculated expression @@ -89,10 +88,6 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); - /* 1. getType */ KX_PYMETHOD_DOC_NOARGS(SCA_PropertySensor,GetType); /* 2. setType */ diff --git a/source/gameengine/GameLogic/SCA_PythonController.cpp b/source/gameengine/GameLogic/SCA_PythonController.cpp index 80e4f54c9c5..ffd95f00699 100644 --- a/source/gameengine/GameLogic/SCA_PythonController.cpp +++ b/source/gameengine/GameLogic/SCA_PythonController.cpp @@ -47,10 +47,8 @@ SCA_PythonController* SCA_PythonController::m_sCurrentController = NULL; -SCA_PythonController::SCA_PythonController(SCA_IObject* gameobj, - int mode, - PyTypeObject* T) - : SCA_IController(gameobj, T), +SCA_PythonController::SCA_PythonController(SCA_IObject* gameobj, int mode) + : SCA_IController(gameobj), m_bytecode(NULL), m_function(NULL), m_function_argc(0), @@ -150,7 +148,7 @@ void SCA_PythonController::SetDictionary(PyObject* pythondictionary) /* Without __file__ set the sys.argv[0] is used for the filename * which ends up with lines from the blender binary being printed in the console */ - PyDict_SetItemString(m_pythondictionary, "__file__", PyString_FromString(m_scriptName.Ptr())); + PyDict_SetItemString(m_pythondictionary, "__file__", PyUnicode_FromString(m_scriptName.Ptr())); } @@ -180,16 +178,16 @@ SCA_IActuator* SCA_PythonController::LinkedActuatorFromPy(PyObject *value) std::vector lacts = m_sCurrentController->GetLinkedActuators(); std::vector::iterator it; - if (PyString_Check(value)) { + if (PyUnicode_Check(value)) { /* get the actuator from the name */ - char *name= PyString_AsString(value); + char *name= _PyUnicode_AsString(value); for(it = lacts.begin(); it!= lacts.end(); ++it) { if( name == (*it)->GetName() ) { return *it; } } } - else if (BGE_PROXY_CHECK_TYPE(value)) { + else if (PyObject_TypeCheck(value, &SCA_IActuator::Type)) { PyObjectPlus *value_plus= BGE_PROXY_REF(value); for(it = lacts.begin(); it!= lacts.end(); ++it) { if( static_cast(value_plus) == (*it) ) { @@ -200,7 +198,7 @@ SCA_IActuator* SCA_PythonController::LinkedActuatorFromPy(PyObject *value) /* set the exception */ PyObject *value_str = PyObject_Repr(value); /* new ref */ - PyErr_Format(PyExc_ValueError, "'%s' not in this python controllers actuator list", PyString_AsString(value_str)); + PyErr_Format(PyExc_ValueError, "'%s' not in this python controllers actuator list", _PyUnicode_AsString(value_str)); Py_DECREF(value_str); return false; @@ -245,19 +243,17 @@ PyTypeObject SCA_PythonController::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, + &SCA_IController::Type, + 0,0,0,0,0,0, + py_base_new }; -PyParentObject SCA_PythonController::Parents[] = { - &SCA_PythonController::Type, - &SCA_IController::Type, - &CValue::Type, - NULL -}; PyMethodDef SCA_PythonController::Methods[] = { {"activate", (PyCFunction) SCA_PythonController::sPyActivate, METH_O}, {"deactivate", (PyCFunction) SCA_PythonController::sPyDeActivate, METH_O}, @@ -490,22 +486,6 @@ void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr) m_sCurrentController = NULL; } - - -PyObject* SCA_PythonController::py_getattro(PyObject *attr) -{ - py_getattro_up(SCA_IController); -} - -PyObject* SCA_PythonController::py_getattro_dict() { - py_getattro_dict_up(SCA_IController); -} - -int SCA_PythonController::py_setattro(PyObject *attr, PyObject *value) -{ - py_setattro_up(SCA_IController); -} - PyObject* SCA_PythonController::PyActivate(PyObject *value) { if(m_sCurrentController != this) { @@ -540,13 +520,13 @@ PyObject* SCA_PythonController::PyDeActivate(PyObject *value) PyObject* SCA_PythonController::PyGetScript() { ShowDeprecationWarning("getScript()", "the script property"); - return PyString_FromString(m_scriptText); + return PyUnicode_FromString(m_scriptText); } /* 2. setScript */ PyObject* SCA_PythonController::PySetScript(PyObject* value) { - char *scriptArg = PyString_AsString(value); + char *scriptArg = _PyUnicode_AsString(value); ShowDeprecationWarning("setScript()", "the script property"); @@ -565,15 +545,20 @@ PyObject* SCA_PythonController::PySetScript(PyObject* value) PyObject* SCA_PythonController::pyattr_get_script(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { + //SCA_PythonController* self= static_cast(static_cast(static_cast(static_cast(static_cast(self_v))))); + // static_cast(dynamic_cast(obj)) - static_cast(obj) + SCA_PythonController* self= static_cast(self_v); - return PyString_FromString(self->m_scriptText); + return PyUnicode_FromString(self->m_scriptText); } + + int SCA_PythonController::pyattr_set_script(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { SCA_PythonController* self= static_cast(self_v); - char *scriptArg = PyString_AsString(value); + char *scriptArg = _PyUnicode_AsString(value); if (scriptArg==NULL) { PyErr_SetString(PyExc_TypeError, "controller.script = string: Python Controller, expected a string script text"); diff --git a/source/gameengine/GameLogic/SCA_PythonController.h b/source/gameengine/GameLogic/SCA_PythonController.h index 0c2af79c3a3..9311b3f355e 100644 --- a/source/gameengine/GameLogic/SCA_PythonController.h +++ b/source/gameengine/GameLogic/SCA_PythonController.h @@ -72,7 +72,7 @@ class SCA_PythonController : public SCA_IController //virtual CValue* AddRef(); //virtual int Release(); // Release a reference to this value (when reference count reaches 0, the value is removed from the heap) - SCA_PythonController(SCA_IObject* gameobj, int mode, PyTypeObject* T = &Type); + SCA_PythonController(SCA_IObject* gameobj, int mode); virtual ~SCA_PythonController(); virtual CValue* GetReplica(); @@ -96,10 +96,6 @@ class SCA_PythonController : public SCA_IController static PyObject* sPyAddActiveActuator(PyObject* self, PyObject* args); static SCA_IActuator* LinkedActuatorFromPy(PyObject *value); - - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); KX_PYMETHOD_O(SCA_PythonController,Activate); diff --git a/source/gameengine/GameLogic/SCA_RandomActuator.cpp b/source/gameengine/GameLogic/SCA_RandomActuator.cpp index a722590dd10..e903d10f9a5 100644 --- a/source/gameengine/GameLogic/SCA_RandomActuator.cpp +++ b/source/gameengine/GameLogic/SCA_RandomActuator.cpp @@ -50,9 +50,8 @@ SCA_RandomActuator::SCA_RandomActuator(SCA_IObject *gameobj, SCA_RandomActuator::KX_RANDOMACT_MODE mode, float para1, float para2, - const STR_String &propName, - PyTypeObject* T) - : SCA_IActuator(gameobj, T), + const STR_String &propName) + : SCA_IActuator(gameobj), m_propname(propName), m_parameter1(para1), m_parameter2(para2), @@ -332,19 +331,15 @@ PyTypeObject SCA_RandomActuator::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject SCA_RandomActuator::Parents[] = { - &SCA_RandomActuator::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IActuator::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef SCA_RandomActuator::Methods[] = { @@ -384,14 +379,14 @@ PyAttributeDef SCA_RandomActuator::Attributes[] = { PyObject* SCA_RandomActuator::pyattr_get_seed(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) { SCA_RandomActuator* act = static_cast(self); - return PyInt_FromLong(act->m_base->GetSeed()); + return PyLong_FromSsize_t(act->m_base->GetSeed()); } int SCA_RandomActuator::pyattr_set_seed(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { SCA_RandomActuator* act = static_cast(self); - if (PyInt_Check(value)) { - int ival = PyInt_AsLong(value); + if (PyLong_Check(value)) { + int ival = PyLong_AsSsize_t(value); act->m_base->SetSeed(ival); return PY_SET_ATTR_SUCCESS; } else { @@ -400,19 +395,6 @@ int SCA_RandomActuator::pyattr_set_seed(void *self, const struct KX_PYATTRIBUTE_ } } -PyObject* SCA_RandomActuator::py_getattro(PyObject *attr) { - py_getattro_up(SCA_IActuator); -} - -PyObject* SCA_RandomActuator::py_getattro_dict() { - py_getattro_dict_up(SCA_IActuator); -} - -int SCA_RandomActuator::py_setattro(PyObject *attr, PyObject *value) -{ - py_setattro_up(SCA_IActuator); -} - /* 1. setSeed */ const char SCA_RandomActuator::SetSeed_doc[] = "setSeed(seed)\n" @@ -439,7 +421,7 @@ const char SCA_RandomActuator::GetSeed_doc[] = PyObject* SCA_RandomActuator::PyGetSeed() { ShowDeprecationWarning("getSeed()", "the seed property"); - return PyInt_FromLong(m_base->GetSeed()); + return PyLong_FromSsize_t(m_base->GetSeed()); } /* 4. getPara1 */ @@ -473,7 +455,7 @@ const char SCA_RandomActuator::GetDistribution_doc[] = PyObject* SCA_RandomActuator::PyGetDistribution() { ShowDeprecationWarning("getDistribution()", "the distribution property"); - return PyInt_FromLong(m_distribution); + return PyLong_FromSsize_t(m_distribution); } /* 9. setProperty */ @@ -508,7 +490,7 @@ const char SCA_RandomActuator::GetProperty_doc[] = PyObject* SCA_RandomActuator::PyGetProperty() { ShowDeprecationWarning("getProperty()", "the 'propName' property"); - return PyString_FromString(m_propname); + return PyUnicode_FromString(m_propname); } /* 11. setBoolConst */ diff --git a/source/gameengine/GameLogic/SCA_RandomActuator.h b/source/gameengine/GameLogic/SCA_RandomActuator.h index 59863589b60..c7d3fe21217 100644 --- a/source/gameengine/GameLogic/SCA_RandomActuator.h +++ b/source/gameengine/GameLogic/SCA_RandomActuator.h @@ -85,8 +85,7 @@ class SCA_RandomActuator : public SCA_IActuator KX_RANDOMACT_MODE mode, float para1, float para2, - const STR_String &propName, - PyTypeObject* T=&Type); + const STR_String &propName); virtual ~SCA_RandomActuator(); virtual bool Update(); @@ -97,10 +96,6 @@ class SCA_RandomActuator : public SCA_IActuator /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); - static PyObject* pyattr_get_seed(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_seed(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); diff --git a/source/gameengine/GameLogic/SCA_RandomSensor.cpp b/source/gameengine/GameLogic/SCA_RandomSensor.cpp index d5cbeef01ae..e036a77707e 100644 --- a/source/gameengine/GameLogic/SCA_RandomSensor.cpp +++ b/source/gameengine/GameLogic/SCA_RandomSensor.cpp @@ -46,9 +46,8 @@ SCA_RandomSensor::SCA_RandomSensor(SCA_EventManager* eventmgr, SCA_IObject* gameobj, - int startseed, - PyTypeObject* T) - : SCA_ISensor(gameobj,eventmgr, T) + int startseed) + : SCA_ISensor(gameobj,eventmgr) { m_basegenerator = new SCA_RandomNumberGenerator(startseed); Init(); @@ -147,19 +146,15 @@ PyTypeObject SCA_RandomSensor::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject SCA_RandomSensor::Parents[] = { - &SCA_RandomSensor::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_ISensor::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef SCA_RandomSensor::Methods[] = { @@ -177,19 +172,6 @@ PyAttributeDef SCA_RandomSensor::Attributes[] = { {NULL} //Sentinel }; -PyObject* SCA_RandomSensor::py_getattro(PyObject *attr) { - py_getattro_up(SCA_ISensor); -} - -PyObject* SCA_RandomSensor::py_getattro_dict() { - py_getattro_dict_up(SCA_ISensor); -} - -int SCA_RandomSensor::py_setattro(PyObject *attr, PyObject *value) -{ - py_setattro_up(SCA_ISensor); -} - /* 1. setSeed */ const char SCA_RandomSensor::SetSeed_doc[] = "setSeed(seed)\n" @@ -216,7 +198,7 @@ const char SCA_RandomSensor::GetSeed_doc[] = "\tequal series.\n"; PyObject* SCA_RandomSensor::PyGetSeed() { ShowDeprecationWarning("getSeed()", "the seed property"); - return PyInt_FromLong(m_basegenerator->GetSeed()); + return PyLong_FromSsize_t(m_basegenerator->GetSeed()); } /* 3. getLastDraw */ @@ -225,24 +207,24 @@ const char SCA_RandomSensor::GetLastDraw_doc[] = "\tReturn the last value that was drawn.\n"; PyObject* SCA_RandomSensor::PyGetLastDraw() { ShowDeprecationWarning("getLastDraw()", "the lastDraw property"); - return PyInt_FromLong(m_lastdraw); + return PyLong_FromSsize_t(m_lastdraw); } PyObject* SCA_RandomSensor::pyattr_get_seed(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { SCA_RandomSensor* self= static_cast(self_v); - return PyInt_FromLong(self->m_basegenerator->GetSeed()); + return PyLong_FromSsize_t(self->m_basegenerator->GetSeed()); } int SCA_RandomSensor::pyattr_set_seed(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { SCA_RandomSensor* self= static_cast(self_v); - if (!PyInt_Check(value)) { + if (!PyLong_Check(value)) { PyErr_SetString(PyExc_TypeError, "sensor.seed = int: Random Sensor, expected an integer"); return PY_SET_ATTR_FAIL; } - self->m_basegenerator->SetSeed(PyInt_AsLong(value)); + self->m_basegenerator->SetSeed(PyLong_AsSsize_t(value)); return PY_SET_ATTR_SUCCESS; } diff --git a/source/gameengine/GameLogic/SCA_RandomSensor.h b/source/gameengine/GameLogic/SCA_RandomSensor.h index b2bf2440966..5e66c36cccf 100644 --- a/source/gameengine/GameLogic/SCA_RandomSensor.h +++ b/source/gameengine/GameLogic/SCA_RandomSensor.h @@ -48,8 +48,7 @@ class SCA_RandomSensor : public SCA_ISensor public: SCA_RandomSensor(class SCA_EventManager* rndmgr, SCA_IObject* gameobj, - int startseed, - PyTypeObject* T=&Type); + int startseed); virtual ~SCA_RandomSensor(); virtual CValue* GetReplica(); virtual void ProcessReplica(); @@ -61,10 +60,6 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); - /* 1. setSeed */ KX_PYMETHOD_DOC_VARARGS(SCA_RandomSensor,SetSeed); /* 2. getSeed */ diff --git a/source/gameengine/GameLogic/SCA_XNORController.cpp b/source/gameengine/GameLogic/SCA_XNORController.cpp index aee8e26c21a..527adc70cc6 100644 --- a/source/gameengine/GameLogic/SCA_XNORController.cpp +++ b/source/gameengine/GameLogic/SCA_XNORController.cpp @@ -42,10 +42,9 @@ /* Native functions */ /* ------------------------------------------------------------------------- */ -SCA_XNORController::SCA_XNORController(SCA_IObject* gameobj, - PyTypeObject* T) +SCA_XNORController::SCA_XNORController(SCA_IObject* gameobj) : - SCA_IController(gameobj,T) + SCA_IController(gameobj) { } @@ -120,19 +119,15 @@ PyTypeObject SCA_XNORController::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject SCA_XNORController::Parents[] = { - &SCA_XNORController::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IController::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef SCA_XNORController::Methods[] = { @@ -143,12 +138,4 @@ PyAttributeDef SCA_XNORController::Attributes[] = { { NULL } //Sentinel }; -PyObject* SCA_XNORController::py_getattro(PyObject *attr) { - py_getattro_up(SCA_IController); -} - -PyObject* SCA_XNORController::py_getattro_dict() { - py_getattro_dict_up(SCA_IController); -} - /* eof */ diff --git a/source/gameengine/GameLogic/SCA_XNORController.h b/source/gameengine/GameLogic/SCA_XNORController.h index 4aad5763cb0..18e77fae665 100644 --- a/source/gameengine/GameLogic/SCA_XNORController.h +++ b/source/gameengine/GameLogic/SCA_XNORController.h @@ -39,7 +39,7 @@ class SCA_XNORController : public SCA_IController Py_Header; //virtual void Trigger(class SCA_LogicManager* logicmgr); public: - SCA_XNORController(SCA_IObject* gameobj,PyTypeObject* T=&Type); + SCA_XNORController(SCA_IObject* gameobj); virtual ~SCA_XNORController(); virtual CValue* GetReplica(); virtual void Trigger(SCA_LogicManager* logicmgr); @@ -48,9 +48,6 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - }; #endif //__KX_XNORCONTROLLER diff --git a/source/gameengine/GameLogic/SCA_XORController.cpp b/source/gameengine/GameLogic/SCA_XORController.cpp index 5afb3a750f5..c0916224fe6 100644 --- a/source/gameengine/GameLogic/SCA_XORController.cpp +++ b/source/gameengine/GameLogic/SCA_XORController.cpp @@ -42,10 +42,9 @@ /* Native functions */ /* ------------------------------------------------------------------------- */ -SCA_XORController::SCA_XORController(SCA_IObject* gameobj, - PyTypeObject* T) +SCA_XORController::SCA_XORController(SCA_IObject* gameobj) : - SCA_IController(gameobj,T) + SCA_IController(gameobj) { } @@ -120,19 +119,15 @@ PyTypeObject SCA_XORController::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject SCA_XORController::Parents[] = { - &SCA_XORController::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IController::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef SCA_XORController::Methods[] = { @@ -143,12 +138,4 @@ PyAttributeDef SCA_XORController::Attributes[] = { { NULL } //Sentinel }; -PyObject* SCA_XORController::py_getattro(PyObject *attr) { - py_getattro_up(SCA_IController); -} - -PyObject* SCA_XORController::py_getattro_dict() { - py_getattro_dict_up(SCA_IController); -} - /* eof */ diff --git a/source/gameengine/GameLogic/SCA_XORController.h b/source/gameengine/GameLogic/SCA_XORController.h index feb9f2ed07c..2607a533661 100644 --- a/source/gameengine/GameLogic/SCA_XORController.h +++ b/source/gameengine/GameLogic/SCA_XORController.h @@ -39,18 +39,10 @@ class SCA_XORController : public SCA_IController Py_Header; //virtual void Trigger(class SCA_LogicManager* logicmgr); public: - SCA_XORController(SCA_IObject* gameobj,PyTypeObject* T=&Type); + SCA_XORController(SCA_IObject* gameobj); virtual ~SCA_XORController(); virtual CValue* GetReplica(); virtual void Trigger(SCA_LogicManager* logicmgr); - - /* --------------------------------------------------------------------- */ - /* Python interface ---------------------------------------------------- */ - /* --------------------------------------------------------------------- */ - - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - }; #endif //__KX_XORCONTROLLER diff --git a/source/gameengine/Ketsji/BL_Shader.cpp b/source/gameengine/Ketsji/BL_Shader.cpp index c5c517c8a65..8bde5dd3a51 100644 --- a/source/gameengine/Ketsji/BL_Shader.cpp +++ b/source/gameengine/Ketsji/BL_Shader.cpp @@ -113,8 +113,8 @@ bool BL_Shader::Ok()const return (mShader !=0 && mOk && mUse); } -BL_Shader::BL_Shader(PyTypeObject *T) -: PyObjectPlus(T), +BL_Shader::BL_Shader() +: PyObjectPlus(), mShader(0), mPass(1), mOk(0), @@ -728,17 +728,6 @@ void BL_Shader::SetUniform(int uniform, const int* val, int len) } } - -PyObject* BL_Shader::py_getattro(PyObject *attr) -{ - py_getattro_up(PyObjectPlus); -} - -PyObject* BL_Shader::py_getattro_dict() { - py_getattro_dict_up(PyObjectPlus); -} - - PyMethodDef BL_Shader::Methods[] = { // creation @@ -792,21 +781,17 @@ PyTypeObject BL_Shader::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, + &PyObjectPlus::Type, + 0,0,0,0,0,0, + py_base_new }; - -PyParentObject BL_Shader::Parents[] = { - &BL_Shader::Type, - &PyObjectPlus::Type, - NULL -}; - - KX_PYMETHODDEF_DOC( BL_Shader, setSource," setSource(vertexProgram, fragmentProgram)" ) { if(mShader !=0 && mOk ) @@ -848,17 +833,17 @@ KX_PYMETHODDEF_DOC( BL_Shader, delSource, "delSource( )" ) KX_PYMETHODDEF_DOC( BL_Shader, isValid, "isValid()" ) { - return PyInt_FromLong( ( mShader !=0 && mOk ) ); + return PyLong_FromSsize_t( ( mShader !=0 && mOk ) ); } KX_PYMETHODDEF_DOC( BL_Shader, getVertexProg ,"getVertexProg( )" ) { - return PyString_FromString(vertProg?vertProg:""); + return PyUnicode_FromString(vertProg?vertProg:""); } KX_PYMETHODDEF_DOC( BL_Shader, getFragmentProg ,"getFragmentProg( )" ) { - return PyString_FromString(fragProg?fragProg:""); + return PyUnicode_FromString(fragProg?fragProg:""); } KX_PYMETHODDEF_DOC( BL_Shader, validate, "validate()") @@ -1223,7 +1208,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformiv, "setUniformiv( uniform_name, (list2 for(unsigned int i=0; (i // 1. SetToPropName PyObject* KX_NetworkMessageActuator::PySetToPropName( @@ -240,4 +223,4 @@ PyObject* KX_NetworkMessageActuator::PySetBody( Py_RETURN_NONE; } -// <----- Deprecated \ No newline at end of file +// <----- Deprecated diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.h b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.h index cf92fd46fe0..b4f55f2a466 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.h +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.h @@ -50,8 +50,7 @@ public: const STR_String &toPropName, const STR_String &subject, int bodyType, - const STR_String &body, - PyTypeObject* T=&Type); + const STR_String &body); virtual ~KX_NetworkMessageActuator(); virtual bool Update(); @@ -61,10 +60,6 @@ public: /* Python interface ------------------------------------------- */ /* ------------------------------------------------------------ */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); - // Deprecated -----> KX_PYMETHOD(KX_NetworkMessageActuator, SetToPropName); KX_PYMETHOD(KX_NetworkMessageActuator, SetSubject); diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp index 8ddcd87b66f..78dda1f6db7 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp @@ -50,10 +50,9 @@ KX_NetworkMessageSensor::KX_NetworkMessageSensor( class KX_NetworkEventManager* eventmgr, // our eventmanager class NG_NetworkScene *NetworkScene, // our scene SCA_IObject* gameobj, // the sensor controlling object - const STR_String &subject, - PyTypeObject* T + const STR_String &subject ) : - SCA_ISensor(gameobj,eventmgr,T), + SCA_ISensor(gameobj,eventmgr), m_Networkeventmgr(eventmgr), m_NetworkScene(NetworkScene), m_subject(subject), @@ -182,19 +181,15 @@ PyTypeObject KX_NetworkMessageSensor::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject KX_NetworkMessageSensor::Parents[] = { - &KX_NetworkMessageSensor::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_ISensor::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef KX_NetworkMessageSensor::Methods[] = { @@ -226,18 +221,6 @@ PyAttributeDef KX_NetworkMessageSensor::Attributes[] = { { NULL } //Sentinel }; -PyObject* KX_NetworkMessageSensor::py_getattro(PyObject *attr) { - py_getattro_up(SCA_ISensor); -} - -PyObject* KX_NetworkMessageSensor::py_getattro_dict() { - py_getattro_dict_up(SCA_ISensor); -} - -int KX_NetworkMessageSensor::py_setattro(PyObject *attr, PyObject *value) { - return SCA_ISensor::py_setattro(attr, value); -} - PyObject* KX_NetworkMessageSensor::pyattr_get_bodies(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_NetworkMessageSensor *self = static_cast(self_v); @@ -267,7 +250,7 @@ const char KX_NetworkMessageSensor::SetSubjectFilterText_doc[] = PyObject* KX_NetworkMessageSensor::PySetSubjectFilterText(PyObject* value) { ShowDeprecationWarning("setSubjectFilterText()", "subject"); - char* Subject = PyString_AsString(value); + char* Subject = _PyUnicode_AsString(value); if (Subject==NULL) { PyErr_SetString(PyExc_TypeError, "sensor.tsetSubjectFilterText(string): KX_NetworkMessageSensor, expected a string message"); return NULL; @@ -285,7 +268,7 @@ const char KX_NetworkMessageSensor::GetFrameMessageCount_doc[] = PyObject* KX_NetworkMessageSensor::PyGetFrameMessageCount() { ShowDeprecationWarning("getFrameMessageCount()", "frameMessageCount"); - return PyInt_FromLong(long(m_frame_message_count)); + return PyLong_FromSsize_t(long(m_frame_message_count)); } // 3. Get the message bodies @@ -311,7 +294,7 @@ const char KX_NetworkMessageSensor::GetSubject_doc[] = PyObject* KX_NetworkMessageSensor::PyGetSubject() { ShowDeprecationWarning("getSubject()", "subject"); - return PyString_FromString(m_subject ? m_subject : ""); + return PyUnicode_FromString(m_subject ? m_subject : ""); } // 5. Get the message subjects @@ -328,4 +311,4 @@ PyObject* KX_NetworkMessageSensor::PyGetSubjects() return (new CListValue())->NewProxy(true); } } -// <----- Deprecated \ No newline at end of file +// <----- Deprecated diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h index 53183f33826..ade87697303 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h @@ -57,8 +57,7 @@ public: KX_NetworkEventManager* eventmgr, // our eventmanager NG_NetworkScene *NetworkScene, // our scene SCA_IObject* gameobj, // the sensor controlling object - const STR_String &subject, - PyTypeObject* T=&Type + const STR_String &subject ); virtual ~KX_NetworkMessageSensor(); @@ -72,10 +71,6 @@ public: /* Python interface -------------------------------------------- */ /* ------------------------------------------------------------- */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); - // Deprecated -----> KX_PYMETHOD_DOC_O(KX_NetworkMessageSensor, SetSubjectFilterText); KX_PYMETHOD_DOC_NOARGS(KX_NetworkMessageSensor, GetFrameMessageCount); diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp index 30057fc039d..314becc702d 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp @@ -42,10 +42,8 @@ BL_BlenderShader *KX_BlenderMaterial::mLastBlenderShader = NULL; //static PyObject *gTextureDict = 0; -KX_BlenderMaterial::KX_BlenderMaterial( - PyTypeObject *T - ) -: PyObjectPlus(T), +KX_BlenderMaterial::KX_BlenderMaterial() +: PyObjectPlus(), RAS_IPolyMaterial(), mMaterial(NULL), mShader(0), @@ -813,36 +811,17 @@ PyTypeObject KX_BlenderMaterial::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, + &PyObjectPlus::Type, + 0,0,0,0,0,0, + py_base_new }; - -PyParentObject KX_BlenderMaterial::Parents[] = { - &KX_BlenderMaterial::Type, - &PyObjectPlus::Type, - NULL -}; - - -PyObject* KX_BlenderMaterial::py_getattro(PyObject *attr) -{ - py_getattro_up(PyObjectPlus); -} - -PyObject* KX_BlenderMaterial::py_getattro_dict() { - py_getattro_dict_up(PyObjectPlus); -} - -int KX_BlenderMaterial::py_setattro(PyObject *attr, PyObject *pyvalue) -{ - return PyObjectPlus::py_setattro(attr, pyvalue); -} - - KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getShader , "getShader()") { if( !GLEW_ARB_fragment_shader) { @@ -912,7 +891,7 @@ void KX_BlenderMaterial::SetBlenderGLSLShader(int layer) KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getMaterialIndex, "getMaterialIndex()") { - return PyInt_FromLong( GetMaterialIndex() ); + return PyLong_FromSsize_t( GetMaterialIndex() ); } KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getTexture, "getTexture( index )" ) diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.h b/source/gameengine/Ketsji/KX_BlenderMaterial.h index b29f2df98db..1f5edc1d7d1 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.h +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.h @@ -23,9 +23,7 @@ class KX_BlenderMaterial : public PyObjectPlus, public RAS_IPolyMaterial Py_Header; public: // -------------------------------- - KX_BlenderMaterial( - PyTypeObject* T=&Type - ); + KX_BlenderMaterial(); void Initialize( class KX_Scene* scene, BL_Material* mat, @@ -83,10 +81,7 @@ public: ); // -------------------------------- - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *pyvalue); - virtual PyObject* py_repr(void) { return PyString_FromString(mMaterial->matname.ReadPtr()); } + virtual PyObject* py_repr(void) { return PyUnicode_FromString(mMaterial->matname.ReadPtr()); } KX_PYMETHOD_DOC( KX_BlenderMaterial, getShader ); KX_PYMETHOD_DOC( KX_BlenderMaterial, getMaterialIndex ); diff --git a/source/gameengine/Ketsji/KX_CDActuator.cpp b/source/gameengine/Ketsji/KX_CDActuator.cpp index 8511526fd5f..bfca81f45d9 100644 --- a/source/gameengine/Ketsji/KX_CDActuator.cpp +++ b/source/gameengine/Ketsji/KX_CDActuator.cpp @@ -48,9 +48,8 @@ KX_CDActuator::KX_CDActuator(SCA_IObject* gameobject, KX_CDACT_TYPE type, int track, short start, - short end, - PyTypeObject* T) - : SCA_IActuator(gameobject,T) + short end) + : SCA_IActuator(gameobject) { m_soundscene = soundscene; m_type = type; @@ -171,25 +170,17 @@ PyTypeObject KX_CDActuator::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - - - -PyParentObject KX_CDActuator::Parents[] = { - &KX_CDActuator::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IActuator::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; - - PyMethodDef KX_CDActuator::Methods[] = { // Deprecated -----> {"setGain",(PyCFunction) KX_CDActuator::sPySetGain,METH_VARARGS,NULL}, @@ -217,22 +208,6 @@ int KX_CDActuator::pyattr_setGain(void *self, const struct KX_PYATTRIBUTE_DEF *a return PY_SET_ATTR_SUCCESS; } -PyObject* KX_CDActuator::py_getattro(PyObject *attr) -{ - py_getattro_up(SCA_IActuator); -} - -PyObject* KX_CDActuator::py_getattro_dict() { - py_getattro_dict_up(SCA_IActuator); -} - -int KX_CDActuator::py_setattro(PyObject *attr, PyObject *value) -{ - py_setattro_up(SCA_IActuator); -} - - - KX_PYMETHODDEF_DOC_NOARGS(KX_CDActuator, startCD, "startCD()\n" "\tStarts the CD playing.\n") @@ -273,8 +248,8 @@ KX_PYMETHODDEF_DOC_O(KX_CDActuator, playTrack, "playTrack(trackNumber)\n" "\tPlays the track selected.\n") { - if (PyInt_Check(value)) { - int track = PyInt_AsLong(value); + if (PyLong_Check(value)) { + int track = PyLong_AsSsize_t(value); SND_CDObject::Instance()->SetPlaymode(SND_CD_TRACK); SND_CDObject::Instance()->SetTrack(track); SND_CDObject::Instance()->SetPlaystate(SND_MUST_PLAY); diff --git a/source/gameengine/Ketsji/KX_CDActuator.h b/source/gameengine/Ketsji/KX_CDActuator.h index 2fd05ab72e5..b01ad73777e 100644 --- a/source/gameengine/Ketsji/KX_CDActuator.h +++ b/source/gameengine/Ketsji/KX_CDActuator.h @@ -68,8 +68,7 @@ public: KX_CDACT_TYPE type, int track, short start, - short end, - PyTypeObject* T=&Type); + short end); ~KX_CDActuator(); @@ -81,10 +80,6 @@ public: /* Python interface --------------------------------------------------- */ /* -------------------------------------------------------------------- */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); - // Deprecated -----> KX_PYMETHOD_VARARGS(KX_CDActuator,SetGain); KX_PYMETHOD_VARARGS(KX_CDActuator,GetGain); diff --git a/source/gameengine/Ketsji/KX_Camera.cpp b/source/gameengine/Ketsji/KX_Camera.cpp index 40f6c99c03c..f762699f780 100644 --- a/source/gameengine/Ketsji/KX_Camera.cpp +++ b/source/gameengine/Ketsji/KX_Camera.cpp @@ -42,10 +42,9 @@ KX_Camera::KX_Camera(void* sgReplicationInfo, SG_Callbacks callbacks, const RAS_CameraData& camdata, bool frustum_culling, - bool delete_node, - PyTypeObject *T) + bool delete_node) : - KX_GameObject(sgReplicationInfo,callbacks,T), + KX_GameObject(sgReplicationInfo,callbacks), m_camdata(camdata), m_dirty(true), m_normalized(false), @@ -551,41 +550,19 @@ PyTypeObject KX_Camera::Type = { &KX_GameObject::Sequence, &KX_GameObject::Mapping, 0,0,0, - py_base_getattro, - py_base_setattro, + NULL, + NULL, 0, - Py_TPFLAGS_DEFAULT, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, 0,0,0,0,0,0,0, - Methods + Methods, + 0, + 0, + &KX_GameObject::Type, + 0,0,0,0,0,0, + py_base_new }; - - - - - -PyParentObject KX_Camera::Parents[] = { - &KX_Camera::Type, - &KX_GameObject::Type, - &SCA_IObject::Type, - &CValue::Type, - NULL -}; - -PyObject* KX_Camera::py_getattro(PyObject *attr) -{ - py_getattro_up(KX_GameObject); -} - -PyObject* KX_Camera::py_getattro_dict() { - py_getattro_dict_up(KX_GameObject); -} - -int KX_Camera::py_setattro(PyObject *attr, PyObject *value) -{ - py_setattro_up(KX_GameObject); -} - KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, sphereInsideFrustum, "sphereInsideFrustum(center, radius) -> Integer\n" "\treturns INSIDE, OUTSIDE or INTERSECT if the given sphere is\n" @@ -611,7 +588,7 @@ KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, sphereInsideFrustum, MT_Point3 center; if (PyVecTo(pycenter, center)) { - return PyInt_FromLong(SphereInsideFrustum(center, radius)); /* new ref */ + return PyLong_FromSsize_t(SphereInsideFrustum(center, radius)); /* new ref */ } } @@ -662,7 +639,7 @@ KX_PYMETHODDEF_DOC_O(KX_Camera, boxInsideFrustum, return NULL; } - return PyInt_FromLong(BoxInsideFrustum(box)); /* new ref */ + return PyLong_FromSsize_t(BoxInsideFrustum(box)); /* new ref */ } KX_PYMETHODDEF_DOC_O(KX_Camera, pointInsideFrustum, @@ -684,7 +661,7 @@ KX_PYMETHODDEF_DOC_O(KX_Camera, pointInsideFrustum, MT_Point3 point; if (PyVecTo(value, point)) { - return PyInt_FromLong(PointInsideFrustum(point)); /* new ref */ + return PyLong_FromSsize_t(PointInsideFrustum(point)); /* new ref */ } PyErr_SetString(PyExc_TypeError, "camera.pointInsideFrustum(point): KX_Camera, expected point argument."); @@ -952,11 +929,11 @@ PyObject* KX_Camera::pyattr_get_world_to_camera(void *self_v, const KX_PYATTRIBU PyObject* KX_Camera::pyattr_get_INSIDE(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) -{ return PyInt_FromLong(INSIDE); } +{ return PyLong_FromSsize_t(INSIDE); } PyObject* KX_Camera::pyattr_get_OUTSIDE(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) -{ return PyInt_FromLong(OUTSIDE); } +{ return PyLong_FromSsize_t(OUTSIDE); } PyObject* KX_Camera::pyattr_get_INTERSECT(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) -{ return PyInt_FromLong(INTERSECT); } +{ return PyLong_FromSsize_t(INTERSECT); } bool ConvertPythonToCamera(PyObject * value, KX_Camera **object, bool py_none_ok, const char *error_prefix) @@ -978,14 +955,14 @@ bool ConvertPythonToCamera(PyObject * value, KX_Camera **object, bool py_none_ok } } - if (PyString_Check(value)) { - STR_String value_str = PyString_AsString(value); + if (PyUnicode_Check(value)) { + STR_String value_str = _PyUnicode_AsString(value); *object = KX_GetActiveScene()->FindCamera(value_str); if (*object) { return true; } else { - PyErr_Format(PyExc_ValueError, "%s, requested name \"%s\" did not match any KX_Camera in this scene", error_prefix, PyString_AsString(value)); + PyErr_Format(PyExc_ValueError, "%s, requested name \"%s\" did not match any KX_Camera in this scene", error_prefix, _PyUnicode_AsString(value)); return false; } } @@ -1142,7 +1119,7 @@ KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, getScreenRay, PyTuple_SET_ITEM(argValue, 0, PyObjectFrom(vect)); PyTuple_SET_ITEM(argValue, 1, PyFloat_FromDouble(dist)); if (propName) - PyTuple_SET_ITEM(argValue, 2, PyString_FromString(propName)); + PyTuple_SET_ITEM(argValue, 2, PyUnicode_FromString(propName)); PyObject* ret= this->PyrayCastTo(argValue,NULL); Py_DECREF(argValue); diff --git a/source/gameengine/Ketsji/KX_Camera.h b/source/gameengine/Ketsji/KX_Camera.h index aef21cd91e4..74c8e6d4e4f 100644 --- a/source/gameengine/Ketsji/KX_Camera.h +++ b/source/gameengine/Ketsji/KX_Camera.h @@ -143,7 +143,7 @@ public: enum { INSIDE, INTERSECT, OUTSIDE } ; - KX_Camera(void* sgReplicationInfo,SG_Callbacks callbacks,const RAS_CameraData& camdata, bool frustum_culling = true, bool delete_node = false, PyTypeObject *T = &Type); + KX_Camera(void* sgReplicationInfo,SG_Callbacks callbacks,const RAS_CameraData& camdata, bool frustum_culling = true, bool delete_node = false); virtual ~KX_Camera(); /** @@ -265,6 +265,7 @@ public: */ int GetViewportTop() const; + virtual int GetGameObjectType() { return OBJ_CAMERA; } KX_PYMETHOD_DOC_VARARGS(KX_Camera, sphereInsideFrustum); KX_PYMETHOD_DOC_O(KX_Camera, boxInsideFrustum); @@ -282,10 +283,6 @@ public: KX_PYMETHOD_DOC_O(KX_Camera, getScreenPosition); KX_PYMETHOD_DOC_VARARGS(KX_Camera, getScreenVect); KX_PYMETHOD_DOC_VARARGS(KX_Camera, getScreenRay); - - virtual PyObject* py_getattro(PyObject *attr); /* lens, near, far, projection_matrix */ - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *pyvalue); static PyObject* pyattr_get_perspective(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_perspective(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); diff --git a/source/gameengine/Ketsji/KX_CameraActuator.cpp b/source/gameengine/Ketsji/KX_CameraActuator.cpp index f8557dac2c4..3d3b68ed85d 100644 --- a/source/gameengine/Ketsji/KX_CameraActuator.cpp +++ b/source/gameengine/Ketsji/KX_CameraActuator.cpp @@ -56,10 +56,9 @@ KX_CameraActuator::KX_CameraActuator( float hght, float minhght, float maxhght, - bool xytog, - PyTypeObject* T + bool xytog ): - SCA_IActuator(gameobj, T), + SCA_IActuator(gameobj), m_ob (obj), m_height (hght), m_minHeight (minhght), @@ -385,19 +384,15 @@ PyTypeObject KX_CameraActuator::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject KX_CameraActuator::Parents[] = { - &KX_CameraActuator::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IActuator::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef KX_CameraActuator::Methods[] = { @@ -424,18 +419,6 @@ PyAttributeDef KX_CameraActuator::Attributes[] = { {NULL} }; -PyObject* KX_CameraActuator::py_getattro(PyObject *attr) { - py_getattro_up(SCA_IActuator); -} - -PyObject* KX_CameraActuator::py_getattro_dict() { - py_getattro_dict_up(SCA_IActuator); -} - -int KX_CameraActuator::py_setattro(PyObject *attr, PyObject* value) { - py_setattro_up(SCA_IActuator); -} - /* get obj ---------------------------------------------------------- */ const char KX_CameraActuator::GetObject_doc[] = "getObject(name_only = 1)\n" @@ -454,7 +437,7 @@ PyObject* KX_CameraActuator::PyGetObject(PyObject* args) Py_RETURN_NONE; if (ret_name_only) - return PyString_FromString(m_ob->GetName().ReadPtr()); + return PyUnicode_FromString(m_ob->GetName().ReadPtr()); else return m_ob->GetProxy(); } @@ -579,7 +562,7 @@ const char KX_CameraActuator::GetXY_doc[] = PyObject* KX_CameraActuator::PyGetXY() { ShowDeprecationWarning("getXY()", "the xy property"); - return PyInt_FromLong(m_x); + return PyLong_FromSsize_t(m_x); } PyObject* KX_CameraActuator::pyattr_get_object(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) diff --git a/source/gameengine/Ketsji/KX_CameraActuator.h b/source/gameengine/Ketsji/KX_CameraActuator.h index efa4e2f38d7..057c6fed770 100644 --- a/source/gameengine/Ketsji/KX_CameraActuator.h +++ b/source/gameengine/Ketsji/KX_CameraActuator.h @@ -91,9 +91,7 @@ private : float hght, float minhght, float maxhght, - bool xytog, - PyTypeObject* T=&Type - + bool xytog ); @@ -120,10 +118,6 @@ private : /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject* value); - /* set object to look at */ KX_PYMETHOD_DOC_O(KX_CameraActuator,SetObject); /* get current object */ diff --git a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp index bd03dea486b..d09eae647c8 100644 --- a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp +++ b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp @@ -54,9 +54,8 @@ KX_ConstraintActuator::KX_ConstraintActuator(SCA_IObject *gameobj, int locrotxyz, int time, int option, - char *property, - PyTypeObject* T) : - SCA_IActuator(gameobj, T), + char *property) : + SCA_IActuator(gameobj), m_refDirVector(refDir), m_currentTime(0) { @@ -581,19 +580,15 @@ PyTypeObject KX_ConstraintActuator::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject KX_ConstraintActuator::Parents[] = { - &KX_ConstraintActuator::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IActuator::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef KX_ConstraintActuator::Methods[] = { @@ -639,21 +634,6 @@ PyAttributeDef KX_ConstraintActuator::Attributes[] = { { NULL } //Sentinel }; -PyObject* KX_ConstraintActuator::py_getattro(PyObject *attr) -{ - py_getattro_up(SCA_IActuator); -} - -PyObject* KX_ConstraintActuator::py_getattro_dict() { - py_getattro_dict_up(SCA_IActuator); -} - -int KX_ConstraintActuator::py_setattro(PyObject *attr, PyObject* value) -{ - py_setattro_up(SCA_IActuator); -} - - int KX_ConstraintActuator::pyattr_check_direction(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) { KX_ConstraintActuator* act = static_cast(self); @@ -691,7 +671,7 @@ const char KX_ConstraintActuator::GetDamp_doc[] = "\tReturns the damping parameter.\n"; PyObject* KX_ConstraintActuator::PyGetDamp(){ ShowDeprecationWarning("getDamp()", "the damp property"); - return PyInt_FromLong(m_posDampTime); + return PyLong_FromSsize_t(m_posDampTime); } /* 2. setRotDamp */ @@ -718,7 +698,7 @@ const char KX_ConstraintActuator::GetRotDamp_doc[] = "\tReturns the damping time for application of the constraint.\n"; PyObject* KX_ConstraintActuator::PyGetRotDamp(){ ShowDeprecationWarning("getRotDamp()", "the rotDamp property"); - return PyInt_FromLong(m_rotDampTime); + return PyLong_FromSsize_t(m_rotDampTime); } /* 2. setDirection */ @@ -791,7 +771,7 @@ const char KX_ConstraintActuator::GetOption_doc[] = "\tReturns the option parameter.\n"; PyObject* KX_ConstraintActuator::PyGetOption(){ ShowDeprecationWarning("getOption()", "the option property"); - return PyInt_FromLong(m_option); + return PyLong_FromSsize_t(m_option); } /* 2. setTime */ @@ -820,7 +800,7 @@ const char KX_ConstraintActuator::GetTime_doc[] = "\tReturns the time parameter.\n"; PyObject* KX_ConstraintActuator::PyGetTime(){ ShowDeprecationWarning("getTime()", "the time property"); - return PyInt_FromLong(m_activeTime); + return PyLong_FromSsize_t(m_activeTime); } /* 2. setProperty */ @@ -849,7 +829,7 @@ const char KX_ConstraintActuator::GetProperty_doc[] = "\tReturns the property parameter.\n"; PyObject* KX_ConstraintActuator::PyGetProperty(){ ShowDeprecationWarning("getProperty()", "the 'property' property"); - return PyString_FromString(m_property.Ptr()); + return PyUnicode_FromString(m_property.Ptr()); } /* 4. setDistance */ @@ -978,7 +958,7 @@ const char KX_ConstraintActuator::GetLimit_doc[] = "\tReturns the type of constraint.\n"; PyObject* KX_ConstraintActuator::PyGetLimit() { ShowDeprecationWarning("setLimit()", "the limit property"); - return PyInt_FromLong(m_locrot); + return PyLong_FromSsize_t(m_locrot); } /* eof */ diff --git a/source/gameengine/Ketsji/KX_ConstraintActuator.h b/source/gameengine/Ketsji/KX_ConstraintActuator.h index 40607b44947..677904aedc9 100644 --- a/source/gameengine/Ketsji/KX_ConstraintActuator.h +++ b/source/gameengine/Ketsji/KX_ConstraintActuator.h @@ -126,8 +126,7 @@ protected: int locrot, int time, int option, - char *property, - PyTypeObject* T=&Type); + char *property); virtual ~KX_ConstraintActuator(); virtual CValue* GetReplica() { KX_ConstraintActuator* replica = new KX_ConstraintActuator(*this); @@ -141,10 +140,6 @@ protected: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject* value); - static int pyattr_check_direction(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_check_min(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); diff --git a/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp b/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp index c5cf67af67d..ec7bb470235 100644 --- a/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp +++ b/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp @@ -38,8 +38,8 @@ KX_ConstraintWrapper::KX_ConstraintWrapper( PHY_ConstraintType ctype, int constraintId, - PHY_IPhysicsEnvironment* physenv,PyTypeObject *T) : - PyObjectPlus(T), + PHY_IPhysicsEnvironment* physenv) : + PyObjectPlus(), m_constraintId(constraintId), m_constraintType(ctype), m_physenv(physenv) @@ -51,7 +51,7 @@ KX_ConstraintWrapper::~KX_ConstraintWrapper() PyObject* KX_ConstraintWrapper::PyGetConstraintId() { - return PyInt_FromLong(m_constraintId); + return PyLong_FromSsize_t(m_constraintId); } @@ -99,37 +99,17 @@ PyTypeObject KX_ConstraintWrapper::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, + &PyObjectPlus::Type, + 0,0,0,0,0,0, + py_base_new }; -PyParentObject KX_ConstraintWrapper::Parents[] = { - &KX_ConstraintWrapper::Type, - NULL -}; - -//here you can search for existing data members (like mass,friction etc.) -PyObject* KX_ConstraintWrapper::py_getattro(PyObject *attr) -{ - py_getattro_up(PyObjectPlus); -} - -PyObject* KX_ConstraintWrapper::py_getattro_dict() { - py_getattro_dict_up(PyObjectPlus); -} - -int KX_ConstraintWrapper::py_setattro(PyObject *attr,PyObject* value) -{ - py_setattro_up(PyObjectPlus); -}; - - - - - PyMethodDef KX_ConstraintWrapper::Methods[] = { {"getConstraintId",(PyCFunction) KX_ConstraintWrapper::sPyGetConstraintId, METH_NOARGS}, {"setParam",(PyCFunction) KX_ConstraintWrapper::sPySetParam, METH_VARARGS}, diff --git a/source/gameengine/Ketsji/KX_ConstraintWrapper.h b/source/gameengine/Ketsji/KX_ConstraintWrapper.h index 03813e0f167..74670944415 100644 --- a/source/gameengine/Ketsji/KX_ConstraintWrapper.h +++ b/source/gameengine/Ketsji/KX_ConstraintWrapper.h @@ -35,11 +35,8 @@ class KX_ConstraintWrapper : public PyObjectPlus { Py_Header; - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); public: - KX_ConstraintWrapper(PHY_ConstraintType ctype,int constraintId,class PHY_IPhysicsEnvironment* physenv,PyTypeObject *T = &Type); + KX_ConstraintWrapper(PHY_ConstraintType ctype,int constraintId,class PHY_IPhysicsEnvironment* physenv); virtual ~KX_ConstraintWrapper (); int getConstraintId() { return m_constraintId;}; diff --git a/source/gameengine/Ketsji/KX_GameActuator.cpp b/source/gameengine/Ketsji/KX_GameActuator.cpp index 28bf12f5e87..560c7fa4bb4 100644 --- a/source/gameengine/Ketsji/KX_GameActuator.cpp +++ b/source/gameengine/Ketsji/KX_GameActuator.cpp @@ -49,9 +49,8 @@ KX_GameActuator::KX_GameActuator(SCA_IObject *gameobj, const STR_String& filename, const STR_String& loadinganimationname, KX_Scene* scene, - KX_KetsjiEngine* ketsjiengine, - PyTypeObject* T) - : SCA_IActuator(gameobj, T) + KX_KetsjiEngine* ketsjiengine) + : SCA_IActuator(gameobj) { m_mode = mode; m_filename = filename; @@ -224,26 +223,17 @@ PyTypeObject KX_GameActuator::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - - - -PyParentObject KX_GameActuator::Parents[] = -{ - &KX_GameActuator::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IActuator::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; - - PyMethodDef KX_GameActuator::Methods[] = { // Deprecated -----> @@ -259,21 +249,6 @@ PyAttributeDef KX_GameActuator::Attributes[] = { { NULL } //Sentinel }; -PyObject* KX_GameActuator::py_getattro(PyObject *attr) -{ - py_getattro_up(SCA_IActuator); -} - -PyObject* KX_GameActuator::py_getattro_dict() { - py_getattro_dict_up(SCA_IActuator); -} - -int KX_GameActuator::py_setattro(PyObject *attr, PyObject *value) -{ - py_setattro_up(SCA_IActuator); -} - - // Deprecated -----> /* getFile */ const char KX_GameActuator::GetFile_doc[] = @@ -282,7 +257,7 @@ const char KX_GameActuator::GetFile_doc[] = PyObject* KX_GameActuator::PyGetFile(PyObject* args, PyObject* kwds) { ShowDeprecationWarning("getFile()", "the fileName property"); - return PyString_FromString(m_filename); + return PyUnicode_FromString(m_filename); } /* setFile */ diff --git a/source/gameengine/Ketsji/KX_GameActuator.h b/source/gameengine/Ketsji/KX_GameActuator.h index b2b1d6ec2b9..cabbf827b40 100644 --- a/source/gameengine/Ketsji/KX_GameActuator.h +++ b/source/gameengine/Ketsji/KX_GameActuator.h @@ -65,8 +65,7 @@ protected: const STR_String& filename, const STR_String& loadinganimationname, KX_Scene* scene, - KX_KetsjiEngine* ketsjiEngine, - PyTypeObject* T=&Type); + KX_KetsjiEngine* ketsjiEngine); virtual ~KX_GameActuator(); virtual CValue* GetReplica(); @@ -77,10 +76,6 @@ protected: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); - // Deprecated functions -----> KX_PYMETHOD_DOC(KX_GameActuator,GetFile); KX_PYMETHOD_DOC(KX_GameActuator,SetFile); diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 577f767b475..bf80eec36d9 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -86,10 +86,8 @@ static MT_Matrix3x3 dummy_orientation = MT_Matrix3x3( 1.0, 0.0, 0.0, KX_GameObject::KX_GameObject( void* sgReplicationInfo, - SG_Callbacks callbacks, - PyTypeObject* T -) : - SCA_IObject(T), + SG_Callbacks callbacks) + : SCA_IObject(), m_bDyna(false), m_layer(0), m_pBlenderObject(NULL), @@ -1498,7 +1496,7 @@ PyObject* KX_GameObject::PyGetPosition() static PyObject *Map_GetItem(PyObject *self_v, PyObject *item) { KX_GameObject* self= static_castBGE_PROXY_REF(self_v); - const char *attr_str= PyString_AsString(item); + const char *attr_str= _PyUnicode_AsString(item); CValue* resultattr; PyObject* pyconvert; @@ -1532,7 +1530,7 @@ static PyObject *Map_GetItem(PyObject *self_v, PyObject *item) static int Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val) { KX_GameObject* self= static_castBGE_PROXY_REF(self_v); - const char *attr_str= PyString_AsString(key); + const char *attr_str= _PyUnicode_AsString(key); if(attr_str==NULL) PyErr_Clear(); @@ -1564,7 +1562,7 @@ static int Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val) int set= 0; /* as CValue */ - if(attr_str && BGE_PROXY_CHECK_TYPE(val)==0) /* dont allow GameObjects for eg to be assigned to CValue props */ + if(attr_str && PyObject_TypeCheck(val, &PyObjectPlus::Type)==0) /* dont allow GameObjects for eg to be assigned to CValue props */ { CValue* vallie = self->ConvertPythonToValue(val, ""); /* error unused */ @@ -1626,7 +1624,7 @@ static int Seq_Contains(PyObject *self_v, PyObject *value) return -1; } - if(PyString_Check(value) && self->GetProperty(PyString_AsString(value))) + if(PyUnicode_Check(value) && self->GetProperty(_PyUnicode_AsString(value))) return 1; if (self->m_attr_dict && PyDict_GetItem(self->m_attr_dict, value)) @@ -1674,30 +1672,23 @@ PyTypeObject KX_GameObject::Type = { &Sequence, &Mapping, 0,0,0, - py_base_getattro, - py_base_setattro, + NULL, + NULL, 0, - Py_TPFLAGS_DEFAULT, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, 0,0,0,0,0,0,0, - Methods -}; - - - - - - -PyParentObject KX_GameObject::Parents[] = { - &KX_GameObject::Type, + Methods, + 0, + 0, &SCA_IObject::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyObject* KX_GameObject::pyattr_get_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_GameObject* self= static_cast(self_v); - return PyString_FromString(self->GetName().ReadPtr()); + return PyUnicode_FromString(self->GetName().ReadPtr()); } PyObject* KX_GameObject::pyattr_get_parent(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) @@ -1922,7 +1913,7 @@ PyObject* KX_GameObject::pyattr_get_localScaling(void *self_v, const KX_PYATTRIB #ifdef USE_MATHUTILS return newVectorObject_cb((PyObject *)self_v, 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_SCALE_LOCAL); #else - return PyObjectFrom(self->NodeGetLocalScale()); + return PyObjectFrom(self->NodeGetLocalScaling()); #endif } @@ -1970,13 +1961,13 @@ PyObject* KX_GameObject::pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF KX_GameObject* self= static_cast(self_v); int state = 0; state |= self->GetState(); - return PyInt_FromLong(state); + return PyLong_FromSsize_t(state); } int KX_GameObject::pyattr_set_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { KX_GameObject* self= static_cast(self_v); - int state_i = PyInt_AsLong(value); + int state_i = PyLong_AsSsize_t(value); unsigned int state = 0; if (state_i == -1 && PyErr_Occurred()) { @@ -2047,128 +2038,6 @@ PyObject* KX_GameObject::pyattr_get_attrDict(void *self_v, const KX_PYATTRIBUTE_ return self->m_attr_dict; } -/* We need these because the macros have a return in them */ -PyObject* KX_GameObject::py_getattro__internal(PyObject *attr) -{ - py_getattro_up(SCA_IObject); -} - -int KX_GameObject::py_setattro__internal(PyObject *attr, PyObject *value) // py_setattro method -{ - py_setattro_up(SCA_IObject); -} - - -PyObject* KX_GameObject::py_getattro(PyObject *attr) -{ - PyObject *object= py_getattro__internal(attr); - - if (object==NULL && m_attr_dict) - { - /* backup the exception incase the attr doesnt exist in the dict either */ - PyObject *err_type, *err_value, *err_tb; - PyErr_Fetch(&err_type, &err_value, &err_tb); - - object= PyDict_GetItem(m_attr_dict, attr); - if (object) { - Py_INCREF(object); - - PyErr_Clear(); - Py_XDECREF( err_type ); - Py_XDECREF( err_value ); - Py_XDECREF( err_tb ); - } - else { - PyErr_Restore(err_type, err_value, err_tb); /* use the error from the parent function */ - } - } - return object; -} - -PyObject* KX_GameObject::py_getattro_dict() { - //py_getattro_dict_up(SCA_IObject); - PyObject *dict= py_getattr_dict(SCA_IObject::py_getattro_dict(), Type.tp_dict); - if(dict==NULL) - return NULL; - - /* normally just return this but KX_GameObject has some more items */ - - - /* Not super fast getting as a list then making into dict keys but its only for dir() */ - PyObject *list= ConvertKeysToPython(); - if(list) - { - int i; - for(i=0; iGetUserData(); } - return PyInt_FromLong((long)physid); + return PyLong_FromSsize_t((long)physid); } PyObject* KX_GameObject::PyGetPropertyNames() @@ -3008,8 +2877,8 @@ PyObject* KX_GameObject::Pyget(PyObject *args) return NULL; - if(PyString_Check(key)) { - CValue *item = GetProperty(PyString_AsString(key)); + if(PyUnicode_Check(key)) { + CValue *item = GetProperty(_PyUnicode_AsString(key)); if (item) { ret = item->ConvertValueToPython(); if(ret) @@ -3078,13 +2947,13 @@ bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py } } - if (PyString_Check(value)) { - *object = (KX_GameObject*)SCA_ILogicBrick::m_sCurrentLogicManager->GetGameObjectByName(STR_String( PyString_AsString(value) )); + if (PyUnicode_Check(value)) { + *object = (KX_GameObject*)SCA_ILogicBrick::m_sCurrentLogicManager->GetGameObjectByName(STR_String( _PyUnicode_AsString(value) )); if (*object) { return true; } else { - PyErr_Format(PyExc_ValueError, "%s, requested name \"%s\" did not match any KX_GameObject in this scene", error_prefix, PyString_AsString(value)); + PyErr_Format(PyExc_ValueError, "%s, requested name \"%s\" did not match any KX_GameObject in this scene", error_prefix, _PyUnicode_AsString(value)); return false; } } diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index 8fa2b3180ef..40f05dddada 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -185,8 +185,7 @@ public: KX_GameObject( void* sgReplicationInfo, - SG_Callbacks callbacks, - PyTypeObject* T=&Type + SG_Callbacks callbacks ); virtual @@ -804,22 +803,10 @@ public: /** * @section Python interface functions. */ - - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); // py_setattro method - virtual int py_delattro(PyObject *attr); virtual PyObject* py_repr(void) { - return PyString_FromString(GetName().ReadPtr()); + return PyUnicode_FromString(GetName().ReadPtr()); } - - - /* quite annoying that we need these but the bloody - * py_getattro_up and py_setattro_up macro's have a returns in them! */ - PyObject* py_getattro__internal(PyObject *attr); - int py_setattro__internal(PyObject *attr, PyObject *value); // py_setattro method - KX_PYMETHOD_NOARGS(KX_GameObject,GetPosition); KX_PYMETHOD_O(KX_GameObject,SetPosition); diff --git a/source/gameengine/Ketsji/KX_IpoActuator.cpp b/source/gameengine/Ketsji/KX_IpoActuator.cpp index 3ec0598ac03..73a370a1681 100644 --- a/source/gameengine/Ketsji/KX_IpoActuator.cpp +++ b/source/gameengine/Ketsji/KX_IpoActuator.cpp @@ -70,9 +70,8 @@ KX_IpoActuator::KX_IpoActuator(SCA_IObject* gameobj, int acttype, bool ipo_as_force, bool ipo_add, - bool ipo_local, - PyTypeObject* T) - : SCA_IActuator(gameobj,T), + bool ipo_local) + : SCA_IActuator(gameobj), m_bNegativeEvent(false), m_startframe (starttime), m_endframe(endtime), @@ -429,19 +428,15 @@ PyTypeObject KX_IpoActuator::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject KX_IpoActuator::Parents[] = { - &KX_IpoActuator::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IActuator::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef KX_IpoActuator::Methods[] = { @@ -477,18 +472,6 @@ PyAttributeDef KX_IpoActuator::Attributes[] = { { NULL } //Sentinel }; -PyObject* KX_IpoActuator::py_getattro(PyObject *attr) { - py_getattro_up(SCA_IActuator); -} - -PyObject* KX_IpoActuator::py_getattro_dict() { - py_getattro_dict_up(SCA_IActuator); -} - -int KX_IpoActuator::py_setattro(PyObject *attr, PyObject *value) // py_setattro method -{ - py_setattro_up(SCA_IActuator); -} /* set --------------------------------------------------------------------- */ const char KX_IpoActuator::Set_doc[] = @@ -689,7 +672,7 @@ const char KX_IpoActuator::GetType_doc[] = "\tReturns the operation mode of the actuator.\n"; PyObject* KX_IpoActuator::PyGetType() { ShowDeprecationWarning("getType()", "the mode property"); - return PyInt_FromLong(m_type); + return PyLong_FromSsize_t(m_type); } /* 10. setForceIpoActsLocal: */ diff --git a/source/gameengine/Ketsji/KX_IpoActuator.h b/source/gameengine/Ketsji/KX_IpoActuator.h index 9ea597def1e..01051ca82dc 100644 --- a/source/gameengine/Ketsji/KX_IpoActuator.h +++ b/source/gameengine/Ketsji/KX_IpoActuator.h @@ -121,8 +121,7 @@ public: int acttype, bool ipo_as_force, bool ipo_add, - bool ipo_local, - PyTypeObject* T=&Type); + bool ipo_local); virtual ~KX_IpoActuator() {}; virtual CValue* GetReplica() { @@ -138,10 +137,6 @@ public: /* --------------------------------------------------------------------- */ /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); //KX_PYMETHOD_DOC KX_PYMETHOD_DOC_VARARGS(KX_IpoActuator,Set); diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp index ae9e097a96e..fb385f8a9a2 100644 --- a/source/gameengine/Ketsji/KX_Light.cpp +++ b/source/gameengine/Ketsji/KX_Light.cpp @@ -51,12 +51,9 @@ KX_LightObject::KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks, class RAS_IRenderTools* rendertools, const RAS_LightObject& lightobj, - bool glsl, - PyTypeObject* T - ) - : - KX_GameObject(sgReplicationInfo,callbacks,T), - m_rendertools(rendertools) + bool glsl) + : KX_GameObject(sgReplicationInfo,callbacks), + m_rendertools(rendertools) { m_lightobj = lightobj; m_lightobj.m_scene = sgReplicationInfo; @@ -271,11 +268,6 @@ void KX_LightObject::UnbindShadowBuffer(RAS_IRasterizer *ras) /* Python Integration Hooks */ /* ------------------------------------------------------------------------- */ -PyObject* KX_LightObject::py_getattro_dict() { - py_getattro_dict_up(KX_GameObject); -} - - PyTypeObject KX_LightObject::Type = { #if (PY_VERSION_HEX >= 0x02060000) PyVarObject_HEAD_INIT(NULL, 0) @@ -297,20 +289,17 @@ PyTypeObject KX_LightObject::Type = { &KX_GameObject::Sequence, &KX_GameObject::Mapping, 0,0,0, - py_base_getattro, - py_base_setattro, + NULL, + NULL, 0, - Py_TPFLAGS_DEFAULT, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, 0,0,0,0,0,0,0, - Methods -}; - -PyParentObject KX_LightObject::Parents[] = { - &KX_LightObject::Type, - &KX_GameObject::Type, - &SCA_IObject::Type, - &CValue::Type, - NULL + Methods, + 0, + 0, + &KX_GameObject::Type, + 0,0,0,0,0,0, + py_base_new }; PyMethodDef KX_LightObject::Methods[] = { @@ -362,11 +351,11 @@ PyObject* KX_LightObject::pyattr_get_typeconst(void *self_v, const KX_PYATTRIBUT const char* type = attrdef->m_name; if(strcmp(type, "SPOT")) { - retvalue = PyInt_FromLong(RAS_LightObject::LIGHT_SPOT); + retvalue = PyLong_FromSsize_t(RAS_LightObject::LIGHT_SPOT); } else if (strcmp(type, "SUN")) { - retvalue = PyInt_FromLong(RAS_LightObject::LIGHT_SUN); + retvalue = PyLong_FromSsize_t(RAS_LightObject::LIGHT_SUN); } else if (strcmp(type, "NORMAL")) { - retvalue = PyInt_FromLong(RAS_LightObject::LIGHT_NORMAL); + retvalue = PyLong_FromSsize_t(RAS_LightObject::LIGHT_NORMAL); } return retvalue; @@ -375,13 +364,13 @@ PyObject* KX_LightObject::pyattr_get_typeconst(void *self_v, const KX_PYATTRIBUT PyObject* KX_LightObject::pyattr_get_type(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_LightObject* self = static_cast(self_v); - return PyInt_FromLong(self->m_lightobj.m_type); + return PyLong_FromSsize_t(self->m_lightobj.m_type); } int KX_LightObject::pyattr_set_type(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject* value) { KX_LightObject* self = static_cast(self_v); - int val = PyInt_AsLong(value); + int val = PyLong_AsSsize_t(value); if((val==-1 && PyErr_Occurred()) || val<0 || val>2) { PyErr_SetString(PyExc_ValueError, "light.type= val: KX_LightObject, expected an int between 0 and 2"); return PY_SET_ATTR_FAIL; @@ -401,14 +390,3 @@ int KX_LightObject::pyattr_set_type(void* self_v, const KX_PYATTRIBUTE_DEF *attr return PY_SET_ATTR_SUCCESS; } - - -PyObject* KX_LightObject::py_getattro(PyObject *attr) -{ - py_getattro_up(KX_GameObject); -} - -int KX_LightObject::py_setattro(PyObject *attr, PyObject *value) -{ - py_setattro_up(KX_GameObject); -} diff --git a/source/gameengine/Ketsji/KX_Light.h b/source/gameengine/Ketsji/KX_Light.h index 358c705080a..0b7ccbe81ab 100644 --- a/source/gameengine/Ketsji/KX_Light.h +++ b/source/gameengine/Ketsji/KX_Light.h @@ -49,7 +49,7 @@ protected: Scene* m_blenderscene; public: - KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks,class RAS_IRenderTools* rendertools,const struct RAS_LightObject& lightobj, bool glsl, PyTypeObject *T = &Type); + KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks,class RAS_IRenderTools* rendertools,const struct RAS_LightObject& lightobj, bool glsl); virtual ~KX_LightObject(); virtual CValue* GetReplica(); RAS_LightObject* GetLightData() { return &m_lightobj;} @@ -64,10 +64,6 @@ public: void BindShadowBuffer(class RAS_IRasterizer *ras, class KX_Camera *cam, class MT_Transform& camtrans); void UnbindShadowBuffer(class RAS_IRasterizer *ras); void Update(); - - virtual PyObject* py_getattro(PyObject *attr); /* lens, near, far, projection_matrix */ - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *pyvalue); /* attributes */ static PyObject* pyattr_get_color(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); diff --git a/source/gameengine/Ketsji/KX_MeshProxy.cpp b/source/gameengine/Ketsji/KX_MeshProxy.cpp index 11effa1ca98..96e8f61e4c8 100644 --- a/source/gameengine/Ketsji/KX_MeshProxy.cpp +++ b/source/gameengine/Ketsji/KX_MeshProxy.cpp @@ -62,18 +62,15 @@ PyTypeObject KX_MeshProxy::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject KX_MeshProxy::Parents[] = { - &KX_MeshProxy::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &CValue::Type, - &PyObjectPlus::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef KX_MeshProxy::Methods[] = { @@ -106,24 +103,8 @@ void KX_MeshProxy::SetMeshModified(bool v) m_meshobj->SetMeshModified(v); } - -PyObject* KX_MeshProxy::py_getattro(PyObject *attr) -{ - py_getattro_up(CValue); -} - -PyObject* KX_MeshProxy::py_getattro_dict() { - py_getattro_dict_up(CValue); -} - -int KX_MeshProxy::py_setattro(PyObject *attr, PyObject* value) -{ - py_setattro_up(CValue); -} - - KX_MeshProxy::KX_MeshProxy(RAS_MeshObject* mesh) - : CValue(&Type), m_meshobj(mesh) + : CValue(), m_meshobj(mesh) { } @@ -150,14 +131,14 @@ PyObject* KX_MeshProxy::PyGetNumMaterials(PyObject* args, PyObject* kwds) { int num = m_meshobj->NumMaterials(); ShowDeprecationWarning("getNumMaterials()", "the numMaterials property"); - return PyInt_FromLong(num); + return PyLong_FromSsize_t(num); } PyObject* KX_MeshProxy::PyGetNumPolygons() { int num = m_meshobj->NumPolygons(); ShowDeprecationWarning("getNumPolygons()", "the numPolygons property"); - return PyInt_FromLong(num); + return PyLong_FromSsize_t(num); } PyObject* KX_MeshProxy::PyGetMaterialName(PyObject* args, PyObject* kwds) @@ -173,7 +154,7 @@ PyObject* KX_MeshProxy::PyGetMaterialName(PyObject* args, PyObject* kwds) return NULL; } - return PyString_FromString(matname.Ptr()); + return PyUnicode_FromString(matname.Ptr()); } @@ -191,7 +172,7 @@ PyObject* KX_MeshProxy::PyGetTextureName(PyObject* args, PyObject* kwds) return NULL; } - return PyString_FromString(matname.Ptr()); + return PyUnicode_FromString(matname.Ptr()); } @@ -214,7 +195,7 @@ PyObject* KX_MeshProxy::PyGetVertexArrayLength(PyObject* args, PyObject* kwds) length = m_meshobj->NumVertices(mat); } - return PyInt_FromLong(length); + return PyLong_FromSsize_t(length); } @@ -304,12 +285,12 @@ PyObject* KX_MeshProxy::pyattr_get_materials(void *self_v, const KX_PYATTRIBUTE_ PyObject * KX_MeshProxy::pyattr_get_numMaterials(void * selfv, const KX_PYATTRIBUTE_DEF * attrdef) { KX_MeshProxy * self = static_cast (selfv); - return PyInt_FromLong(self->m_meshobj->NumMaterials()); + return PyLong_FromSsize_t(self->m_meshobj->NumMaterials()); } PyObject * KX_MeshProxy::pyattr_get_numPolygons(void * selfv, const KX_PYATTRIBUTE_DEF * attrdef) { KX_MeshProxy * self = static_cast (selfv); - return PyInt_FromLong(self->m_meshobj->NumPolygons()); + return PyLong_FromSsize_t(self->m_meshobj->NumPolygons()); } /* a close copy of ConvertPythonToGameObject but for meshes */ @@ -332,13 +313,13 @@ bool ConvertPythonToMesh(PyObject * value, RAS_MeshObject **object, bool py_none } } - if (PyString_Check(value)) { - *object = (RAS_MeshObject*)SCA_ILogicBrick::m_sCurrentLogicManager->GetMeshByName(STR_String( PyString_AsString(value) )); + if (PyUnicode_Check(value)) { + *object = (RAS_MeshObject*)SCA_ILogicBrick::m_sCurrentLogicManager->GetMeshByName(STR_String( _PyUnicode_AsString(value) )); if (*object) { return true; } else { - PyErr_Format(PyExc_ValueError, "%s, requested name \"%s\" did not match any KX_MeshProxy in this scene", error_prefix, PyString_AsString(value)); + PyErr_Format(PyExc_ValueError, "%s, requested name \"%s\" did not match any KX_MeshProxy in this scene", error_prefix, _PyUnicode_AsString(value)); return false; } } diff --git a/source/gameengine/Ketsji/KX_MeshProxy.h b/source/gameengine/Ketsji/KX_MeshProxy.h index bfdd4be4118..4b6543677ad 100644 --- a/source/gameengine/Ketsji/KX_MeshProxy.h +++ b/source/gameengine/Ketsji/KX_MeshProxy.h @@ -56,9 +56,6 @@ public: virtual CValue* GetReplica(); // stuff for python integration - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject* value); KX_PYMETHOD(KX_MeshProxy,GetNumMaterials); // Deprecated KX_PYMETHOD(KX_MeshProxy,GetMaterialName); diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp index fde10a493db..ba4b47cb03f 100644 --- a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp +++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp @@ -63,9 +63,8 @@ KX_MouseFocusSensor::KX_MouseFocusSensor(SCA_MouseManager* eventmgr, int focusmode, KX_Scene* kxscene, KX_KetsjiEngine *kxengine, - SCA_IObject* gameobj, - PyTypeObject* T) - : SCA_MouseSensor(eventmgr, startx, starty, mousemode, gameobj, T), + SCA_IObject* gameobj) + : SCA_MouseSensor(eventmgr, startx, starty, mousemode, gameobj), m_focusmode(focusmode), m_kxscene(kxscene), m_kxengine(kxengine) @@ -356,20 +355,15 @@ PyTypeObject KX_MouseFocusSensor::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject KX_MouseFocusSensor::Parents[] = { - &KX_MouseFocusSensor::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_MouseSensor::Type, - &SCA_ISensor::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef KX_MouseFocusSensor::Methods[] = { @@ -393,15 +387,6 @@ PyAttributeDef KX_MouseFocusSensor::Attributes[] = { { NULL } //Sentinel }; -PyObject* KX_MouseFocusSensor::py_getattro(PyObject *attr) { - py_getattro_up(SCA_MouseSensor); -} - -PyObject* KX_MouseFocusSensor::py_getattro_dict() { - py_getattro_dict_up(SCA_MouseSensor); -} - - const char KX_MouseFocusSensor::GetHitObject_doc[] = "getHitObject()\n" "\tReturns the object that was hit by this ray.\n"; diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.h b/source/gameengine/Ketsji/KX_MouseFocusSensor.h index 29d674eb305..dfada7a59cc 100644 --- a/source/gameengine/Ketsji/KX_MouseFocusSensor.h +++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.h @@ -56,8 +56,7 @@ class KX_MouseFocusSensor : public SCA_MouseSensor int focusmode, KX_Scene* kxscene, KX_KetsjiEngine* kxengine, - SCA_IObject* gameobj, - PyTypeObject* T=&Type ); + SCA_IObject* gameobj); virtual ~KX_MouseFocusSensor() { ; }; virtual CValue* GetReplica() { @@ -89,8 +88,6 @@ class KX_MouseFocusSensor : public SCA_MouseSensor /* --------------------------------------------------------------------- */ /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); KX_PYMETHOD_DOC_NOARGS(KX_MouseFocusSensor,GetRayTarget); KX_PYMETHOD_DOC_NOARGS(KX_MouseFocusSensor,GetRaySource); diff --git a/source/gameengine/Ketsji/KX_NearSensor.cpp b/source/gameengine/Ketsji/KX_NearSensor.cpp index 44842b7f5b3..1a211a64b35 100644 --- a/source/gameengine/Ketsji/KX_NearSensor.cpp +++ b/source/gameengine/Ketsji/KX_NearSensor.cpp @@ -48,15 +48,13 @@ KX_NearSensor::KX_NearSensor(SCA_EventManager* eventmgr, bool bFindMaterial, const STR_String& touchedpropname, class KX_Scene* scene, - PHY_IPhysicsController* ctrl, - PyTypeObject* T) + PHY_IPhysicsController* ctrl) :KX_TouchSensor(eventmgr, gameobj, bFindMaterial, false, - touchedpropname, - /* scene, */ - T), + touchedpropname + /*, scene */), m_Margin(margin), m_ResetMargin(resetmargin) @@ -272,26 +270,17 @@ PyTypeObject KX_NearSensor::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - - - -PyParentObject KX_NearSensor::Parents[] = { - &KX_NearSensor::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &KX_TouchSensor::Type, - &SCA_ISensor::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; - - PyMethodDef KX_NearSensor::Methods[] = { //No methods {NULL,NULL} //Sentinel @@ -302,18 +291,3 @@ PyAttributeDef KX_NearSensor::Attributes[] = { KX_PYATTRIBUTE_FLOAT_RW_CHECK("resetDistance", 0, 100, KX_NearSensor, m_ResetMargin, CheckResetDistance), {NULL} //Sentinel }; - - -PyObject* KX_NearSensor::py_getattro(PyObject *attr) -{ - py_getattro_up(KX_TouchSensor); -} - -PyObject* KX_NearSensor::py_getattro_dict() { - py_getattro_dict_up(KX_TouchSensor); -} - -int KX_NearSensor::py_setattro(PyObject*attr, PyObject* value) -{ - py_setattro_up(KX_TouchSensor); -} diff --git a/source/gameengine/Ketsji/KX_NearSensor.h b/source/gameengine/Ketsji/KX_NearSensor.h index 63099e181a0..f3c1d74805c 100644 --- a/source/gameengine/Ketsji/KX_NearSensor.h +++ b/source/gameengine/Ketsji/KX_NearSensor.h @@ -54,8 +54,7 @@ public: bool bFindMaterial, const STR_String& touchedpropname, class KX_Scene* scene, - PHY_IPhysicsController* ctrl, - PyTypeObject* T=&Type); + PHY_IPhysicsController* ctrl); /* public: KX_NearSensor(class SCA_EventManager* eventmgr, @@ -64,8 +63,7 @@ public: double resetmargin, bool bFindMaterial, const STR_String& touchedpropname, - class KX_Scene* scene, - PyTypeObject* T=&Type); + class KX_Scene* scene); */ virtual ~KX_NearSensor(); virtual void SynchronizeTransform(); @@ -83,9 +81,6 @@ public: /* --------------------------------------------------------------------- */ /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject* value); //No methods diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.cpp b/source/gameengine/Ketsji/KX_ObjectActuator.cpp index 62e61667c56..ae340d12be4 100644 --- a/source/gameengine/Ketsji/KX_ObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_ObjectActuator.cpp @@ -53,10 +53,9 @@ KX_ObjectActuator( const MT_Vector3& linV, const MT_Vector3& angV, const short damping, - const KX_LocalFlags& flag, - PyTypeObject* T + const KX_LocalFlags& flag ) : - SCA_IActuator(gameobj,T), + SCA_IActuator(gameobj), m_force(force), m_torque(torque), m_dloc(dloc), @@ -342,19 +341,15 @@ PyTypeObject KX_ObjectActuator::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject KX_ObjectActuator::Parents[] = { - &KX_ObjectActuator::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IActuator::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef KX_ObjectActuator::Methods[] = { @@ -414,20 +409,6 @@ PyAttributeDef KX_ObjectActuator::Attributes[] = { { NULL } //Sentinel }; -PyObject* KX_ObjectActuator::py_getattro(PyObject *attr) { - py_getattro_up(SCA_IActuator); -} - - -PyObject* KX_ObjectActuator::py_getattro_dict() { - py_getattro_dict_up(SCA_IActuator); -} - -int KX_ObjectActuator::py_setattro(PyObject *attr, PyObject *value) -{ - py_setattro_up(SCA_IActuator); -} - /* Attribute get/set functions */ #ifdef USE_MATHUTILS @@ -574,7 +555,7 @@ int KX_ObjectActuator::pyattr_set_forceLimitX(void *self_v, const KX_PYATTRIBUTE { self->m_drot[0] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 0)); self->m_dloc[0] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 1)); - self->m_bitLocalFlag.Torque = (PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 2)) != 0); + self->m_bitLocalFlag.Torque = (PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 2)) != 0); if (!PyErr_Occurred()) { @@ -610,7 +591,7 @@ int KX_ObjectActuator::pyattr_set_forceLimitY(void *self_v, const KX_PYATTRIBUTE { self->m_drot[1] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 0)); self->m_dloc[1] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 1)); - self->m_bitLocalFlag.DLoc = (PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 2)) != 0); + self->m_bitLocalFlag.DLoc = (PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 2)) != 0); if (!PyErr_Occurred()) { @@ -646,7 +627,7 @@ int KX_ObjectActuator::pyattr_set_forceLimitZ(void *self_v, const KX_PYATTRIBUTE { self->m_drot[2] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 0)); self->m_dloc[2] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 1)); - self->m_bitLocalFlag.DRot = (PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 2)) != 0); + self->m_bitLocalFlag.DRot = (PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 2)) != 0); if (!PyErr_Occurred()) { diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.h b/source/gameengine/Ketsji/KX_ObjectActuator.h index 6ca442b2ec2..20aec9e0e86 100644 --- a/source/gameengine/Ketsji/KX_ObjectActuator.h +++ b/source/gameengine/Ketsji/KX_ObjectActuator.h @@ -135,8 +135,7 @@ public: const MT_Vector3& linV, const MT_Vector3& angV, const short damping, - const KX_LocalFlags& flag, - PyTypeObject* T=&Type + const KX_LocalFlags& flag ); ~KX_ObjectActuator(); CValue* GetReplica(); @@ -163,10 +162,6 @@ public: /* --------------------------------------------------------------------- */ /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetForce); KX_PYMETHOD_VARARGS(KX_ObjectActuator,SetForce); diff --git a/source/gameengine/Ketsji/KX_ParentActuator.cpp b/source/gameengine/Ketsji/KX_ParentActuator.cpp index cd2ed456c48..befa2aaff56 100644 --- a/source/gameengine/Ketsji/KX_ParentActuator.cpp +++ b/source/gameengine/Ketsji/KX_ParentActuator.cpp @@ -50,9 +50,8 @@ KX_ParentActuator::KX_ParentActuator(SCA_IObject *gameobj, int mode, bool addToCompound, bool ghost, - SCA_IObject *ob, - PyTypeObject* T) - : SCA_IActuator(gameobj, T), + SCA_IObject *ob) + : SCA_IActuator(gameobj), m_mode(mode), m_addToCompound(addToCompound), m_ghost(ghost), @@ -157,19 +156,15 @@ PyTypeObject KX_ParentActuator::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject KX_ParentActuator::Parents[] = { - &KX_ParentActuator::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IActuator::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef KX_ParentActuator::Methods[] = { @@ -217,18 +212,6 @@ int KX_ParentActuator::pyattr_set_object(void *self, const struct KX_PYATTRIBUTE } -PyObject* KX_ParentActuator::py_getattro(PyObject *attr) { - py_getattro_up(SCA_IActuator); -} - -PyObject* KX_ParentActuator::py_getattro_dict() { - py_getattro_dict_up(SCA_IActuator); -} - -int KX_ParentActuator::py_setattro(PyObject *attr, PyObject* value) { - py_setattro_up(SCA_IActuator); -} - /* Deprecated -----> */ /* 1. setObject */ const char KX_ParentActuator::SetObject_doc[] = @@ -273,7 +256,7 @@ PyObject* KX_ParentActuator::PyGetObject(PyObject* args) Py_RETURN_NONE; if (ret_name_only) - return PyString_FromString(m_ob->GetName().ReadPtr()); + return PyUnicode_FromString(m_ob->GetName().ReadPtr()); else return m_ob->GetProxy(); } diff --git a/source/gameengine/Ketsji/KX_ParentActuator.h b/source/gameengine/Ketsji/KX_ParentActuator.h index 148375e994c..aeb39eabf89 100644 --- a/source/gameengine/Ketsji/KX_ParentActuator.h +++ b/source/gameengine/Ketsji/KX_ParentActuator.h @@ -68,8 +68,7 @@ class KX_ParentActuator : public SCA_IActuator int mode, bool addToCompound, bool ghost, - SCA_IObject *ob, - PyTypeObject* T=&Type); + SCA_IObject *ob); virtual ~KX_ParentActuator(); virtual bool Update(); @@ -82,10 +81,6 @@ class KX_ParentActuator : public SCA_IActuator /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject* value); - /* These are used to get and set m_ob */ static PyObject* pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); diff --git a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp index c968e50957e..7bce311f1b6 100644 --- a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp +++ b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp @@ -39,8 +39,8 @@ KX_PhysicsObjectWrapper::KX_PhysicsObjectWrapper( PHY_IPhysicsController* ctrl, - PHY_IPhysicsEnvironment* physenv,PyTypeObject *T) : - PyObjectPlus(T), + PHY_IPhysicsEnvironment* physenv) : + PyObjectPlus(), m_ctrl(ctrl), m_physenv(physenv) { @@ -129,46 +129,17 @@ PyTypeObject KX_PhysicsObjectWrapper::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, + &PyObjectPlus::Type, + 0,0,0,0,0,0, + py_base_new }; -PyParentObject KX_PhysicsObjectWrapper::Parents[] = { - &KX_PhysicsObjectWrapper::Type, - NULL -}; - -PyObject* KX_PhysicsObjectWrapper::py_getattro(PyObject *attr) -{ - py_getattro_up(PyObjectPlus); -} - -PyObject* KX_PhysicsObjectWrapper::py_getattro_dict() { - py_getattro_dict_up(PyObjectPlus); -} - -int KX_PhysicsObjectWrapper::py_setattro(PyObject *attr,PyObject *pyobj) -{ - int result = 1; - - if (PyInt_Check(pyobj)) - { - result = 0; - } - if (PyString_Check(pyobj)) - { - result = 0; - } - if (result) - result = PyObjectPlus::py_setattro(attr,pyobj); - - return result; -}; - - PyMethodDef KX_PhysicsObjectWrapper::Methods[] = { {"setPosition",(PyCFunction) KX_PhysicsObjectWrapper::sPySetPosition, METH_VARARGS}, {"setLinearVelocity",(PyCFunction) KX_PhysicsObjectWrapper::sPySetLinearVelocity, METH_VARARGS}, diff --git a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h index 1b59686babc..fa6fd1d1f2a 100644 --- a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h +++ b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h @@ -35,12 +35,8 @@ class KX_PhysicsObjectWrapper : public PyObjectPlus { Py_Header; - - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); public: - KX_PhysicsObjectWrapper(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsEnvironment* physenv,PyTypeObject *T = &Type); + KX_PhysicsObjectWrapper(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsEnvironment* physenv); virtual ~KX_PhysicsObjectWrapper(); KX_PYMETHOD_VARARGS(KX_PhysicsObjectWrapper,SetPosition); diff --git a/source/gameengine/Ketsji/KX_PolyProxy.cpp b/source/gameengine/Ketsji/KX_PolyProxy.cpp index b56b5500c39..a1571b17756 100644 --- a/source/gameengine/Ketsji/KX_PolyProxy.cpp +++ b/source/gameengine/Ketsji/KX_PolyProxy.cpp @@ -55,18 +55,15 @@ PyTypeObject KX_PolyProxy::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject KX_PolyProxy::Parents[] = { - &KX_PolyProxy::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &CValue::Type, - &PyObjectPlus::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef KX_PolyProxy::Methods[] = { @@ -98,16 +95,17 @@ PyAttributeDef KX_PolyProxy::Attributes[] = { { NULL } //Sentinel }; +#if 0 PyObject* KX_PolyProxy::py_getattro(PyObject *attr) { - char *attr_str= PyString_AsString(attr); + char *attr_str= _PyUnicode_AsString(attr); if (!strcmp(attr_str, "matname")) { - return PyString_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetMaterialName()); + return PyUnicode_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetMaterialName()); } if (!strcmp(attr_str, "texture")) { - return PyString_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetTextureName()); + return PyUnicode_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetTextureName()); } if (!strcmp(attr_str, "material")) { @@ -136,38 +134,35 @@ PyObject* KX_PolyProxy::py_getattro(PyObject *attr) // found it break; } - return PyInt_FromLong(matid); + return PyLong_FromSsize_t(matid); } if (!strcmp(attr_str, "v1")) { - return PyInt_FromLong(m_polygon->GetVertexOffset(0)); + return PyLong_FromSsize_t(m_polygon->GetVertexOffset(0)); } if (!strcmp(attr_str, "v2")) { - return PyInt_FromLong(m_polygon->GetVertexOffset(1)); + return PyLong_FromSsize_t(m_polygon->GetVertexOffset(1)); } if (!strcmp(attr_str, "v3")) { - return PyInt_FromLong(m_polygon->GetVertexOffset(2)); + return PyLong_FromSsize_t(m_polygon->GetVertexOffset(2)); } if (!strcmp(attr_str, "v4")) { - return PyInt_FromLong(((m_polygon->VertexCount()>3)?m_polygon->GetVertexOffset(3):0)); + return PyLong_FromSsize_t(((m_polygon->VertexCount()>3)?m_polygon->GetVertexOffset(3):0)); } if (!strcmp(attr_str, "visible")) { - return PyInt_FromLong(m_polygon->IsVisible()); + return PyLong_FromSsize_t(m_polygon->IsVisible()); } if (!strcmp(attr_str, "collide")) { - return PyInt_FromLong(m_polygon->IsCollider()); + return PyLong_FromSsize_t(m_polygon->IsCollider()); } - py_getattro_up(CValue); -} - -PyObject* KX_PolyProxy::py_getattro_dict() { - py_getattro_dict_up(CValue); + // py_getattro_up(CValue); // XXX -- todo, make all these attributes } +#endif KX_PolyProxy::KX_PolyProxy(const RAS_MeshObject*mesh, RAS_Polygon* polygon) : m_polygon(polygon), @@ -204,37 +199,37 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getMaterialIndex, // found it break; } - return PyInt_FromLong(matid); + return PyLong_FromSsize_t(matid); } KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getNumVertex, "getNumVertex() : returns the number of vertex of the polygon, 3 or 4\n") { - return PyInt_FromLong(m_polygon->VertexCount()); + return PyLong_FromSsize_t(m_polygon->VertexCount()); } KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, isVisible, "isVisible() : returns whether the polygon is visible or not\n") { - return PyInt_FromLong(m_polygon->IsVisible()); + return PyLong_FromSsize_t(m_polygon->IsVisible()); } KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, isCollider, "isCollider() : returns whether the polygon is receives collision or not\n") { - return PyInt_FromLong(m_polygon->IsCollider()); + return PyLong_FromSsize_t(m_polygon->IsCollider()); } KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getMaterialName, "getMaterialName() : returns the polygon material name, \"NoMaterial\" if no material\n") { - return PyString_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetMaterialName()); + return PyUnicode_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetMaterialName()); } KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getTextureName, "getTexturelName() : returns the polygon texture name, \"NULL\" if no texture\n") { - return PyString_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetTextureName()); + return PyUnicode_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetTextureName()); } KX_PYMETHODDEF_DOC(KX_PolyProxy, getVertexIndex, @@ -255,9 +250,9 @@ KX_PYMETHODDEF_DOC(KX_PolyProxy, getVertexIndex, } if (index < m_polygon->VertexCount()) { - return PyInt_FromLong(m_polygon->GetVertexOffset(index)); + return PyLong_FromSsize_t(m_polygon->GetVertexOffset(index)); } - return PyInt_FromLong(0); + return PyLong_FromSsize_t(0); } KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getMesh, diff --git a/source/gameengine/Ketsji/KX_PolyProxy.h b/source/gameengine/Ketsji/KX_PolyProxy.h index d8fd36fec6c..e619617d312 100644 --- a/source/gameengine/Ketsji/KX_PolyProxy.h +++ b/source/gameengine/Ketsji/KX_PolyProxy.h @@ -52,8 +52,6 @@ public: // stuff for python integration - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); KX_PYMETHOD_DOC_NOARGS(KX_PolyProxy,getMaterialIndex) KX_PYMETHOD_DOC_NOARGS(KX_PolyProxy,getNumVertex) diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp index 506c167a905..9bc84127572 100644 --- a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp +++ b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp @@ -51,8 +51,8 @@ #include "KX_PyMath.h" -KX_PolygonMaterial::KX_PolygonMaterial(PyTypeObject *T) - : PyObjectPlus(T), +KX_PolygonMaterial::KX_PolygonMaterial() + : PyObjectPlus(), RAS_IPolyMaterial(), m_tface(NULL), @@ -115,7 +115,7 @@ bool KX_PolygonMaterial::Activate(RAS_IRasterizer* rasty, TCachingInfo& cachingI PyObject *ret = PyObject_CallMethod(m_pymaterial, "activate", "(NNO)", pyRasty, pyCachingInfo, (PyObject*) this->m_proxy); if (ret) { - bool value = PyInt_AsLong(ret); + bool value = PyLong_AsSsize_t(ret); Py_DECREF(ret); dopass = value; } @@ -255,33 +255,17 @@ PyTypeObject KX_PolygonMaterial::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, + &PyObjectPlus::Type, + 0,0,0,0,0,0, + py_base_new }; -PyParentObject KX_PolygonMaterial::Parents[] = { - &KX_PolygonMaterial::Type, - &PyObjectPlus::Type, - NULL -}; - -PyObject* KX_PolygonMaterial::py_getattro(PyObject *attr) -{ - py_getattro_up(PyObjectPlus); -} - -PyObject* KX_PolygonMaterial::py_getattro_dict() { - py_getattro_dict_up(PyObjectPlus); -} - -int KX_PolygonMaterial::py_setattro(PyObject *attr, PyObject *value) -{ - py_setattro_up(PyObjectPlus); -} - KX_PYMETHODDEF_DOC(KX_PolygonMaterial, setCustomMaterial, "setCustomMaterial(material)") { PyObject *material; @@ -347,13 +331,13 @@ KX_PYMETHODDEF_DOC(KX_PolygonMaterial, activate, "activate(rasty, cachingInfo)") PyObject* KX_PolygonMaterial::pyattr_get_texture(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_PolygonMaterial* self= static_cast(self_v); - return PyString_FromString(self->m_texturename.ReadPtr()); + return PyUnicode_FromString(self->m_texturename.ReadPtr()); } PyObject* KX_PolygonMaterial::pyattr_get_material(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_PolygonMaterial* self= static_cast(self_v); - return PyString_FromString(self->m_materialname.ReadPtr()); + return PyUnicode_FromString(self->m_materialname.ReadPtr()); } /* this does not seem useful */ @@ -370,7 +354,7 @@ PyObject* KX_PolygonMaterial::pyattr_get_gl_texture(void *self_v, const KX_PYATT if (self->m_tface && self->m_tface->tpage) bindcode= self->m_tface->tpage->bindcode; - return PyInt_FromLong(bindcode); + return PyLong_FromSsize_t(bindcode); } diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.h b/source/gameengine/Ketsji/KX_PolygonMaterial.h index 89ecb026da9..266b4d7e789 100644 --- a/source/gameengine/Ketsji/KX_PolygonMaterial.h +++ b/source/gameengine/Ketsji/KX_PolygonMaterial.h @@ -57,7 +57,7 @@ private: mutable int m_pass; public: - KX_PolygonMaterial(PyTypeObject *T = &Type); + KX_PolygonMaterial(); void Initialize(const STR_String &texname, Material* ma, int materialindex, @@ -116,10 +116,7 @@ public: KX_PYMETHOD_DOC(KX_PolygonMaterial, setCustomMaterial); KX_PYMETHOD_DOC(KX_PolygonMaterial, loadProgram); - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *pyvalue); - virtual PyObject* py_repr(void) { return PyString_FromString(m_material ? ((ID *)m_material)->name+2 : ""); } + virtual PyObject* py_repr(void) { return PyUnicode_FromString(m_material ? ((ID *)m_material)->name+2 : ""); } static PyObject* pyattr_get_texture(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_material(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); diff --git a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp index 4ec901a2f5e..94e8d1fd583 100644 --- a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp +++ b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp @@ -640,7 +640,7 @@ PyObject* initPythonConstraintBinding() // Add some symbolic constants to the module d = PyModule_GetDict(m); - ErrorObject = PyString_FromString("PhysicsConstraints.error"); + ErrorObject = PyUnicode_FromString("PhysicsConstraints.error"); PyDict_SetItemString(d, "error", ErrorObject); Py_DECREF(ErrorObject); diff --git a/source/gameengine/Ketsji/KX_PyMath.cpp b/source/gameengine/Ketsji/KX_PyMath.cpp index 76cfb0e572d..6d33c38190c 100644 --- a/source/gameengine/Ketsji/KX_PyMath.cpp +++ b/source/gameengine/Ketsji/KX_PyMath.cpp @@ -99,7 +99,7 @@ PyObject* PyObjectFrom(const MT_Matrix4x4 &mat) #ifdef USE_MATHUTILS float fmat[16]; mat.getValue(fmat); - return newMatrixObject(fmat, 4, 4, Py_NEW); + return newMatrixObject(fmat, 4, 4, Py_NEW, NULL); #else PyObject *list = PyList_New(4); PyObject *sublist; @@ -123,7 +123,7 @@ PyObject* PyObjectFrom(const MT_Matrix3x3 &mat) #ifdef USE_MATHUTILS float fmat[9]; mat.getValue3x3(fmat); - return newMatrixObject(fmat, 3, 3, Py_NEW); + return newMatrixObject(fmat, 3, 3, Py_NEW, NULL); #else PyObject *list = PyList_New(3); PyObject *sublist; @@ -146,7 +146,7 @@ PyObject* PyObjectFrom(const MT_Quaternion &qrot) { /* NOTE, were re-ordering here for Mathutils compat */ float fvec[4]= {qrot[3], qrot[0], qrot[1], qrot[2]}; - return newQuaternionObject(fvec, Py_WRAP); + return newQuaternionObject(fvec, Py_WRAP, NULL); } #endif @@ -154,7 +154,7 @@ PyObject* PyObjectFrom(const MT_Tuple4 &vec) { #ifdef USE_MATHUTILS float fvec[4]= {vec[0], vec[1], vec[2], vec[3]}; - return newVectorObject(fvec, 4, Py_WRAP); + return newVectorObject(fvec, 4, Py_WRAP, NULL); #else PyObject *list = PyList_New(4); PyList_SET_ITEM(list, 0, PyFloat_FromDouble(vec[0])); @@ -169,7 +169,7 @@ PyObject* PyObjectFrom(const MT_Tuple3 &vec) { #ifdef USE_MATHUTILS float fvec[3]= {vec[0], vec[1], vec[2]}; - return newVectorObject(fvec, 3, Py_WRAP); + return newVectorObject(fvec, 3, Py_WRAP, NULL); #else PyObject *list = PyList_New(3); PyList_SET_ITEM(list, 0, PyFloat_FromDouble(vec[0])); @@ -183,7 +183,7 @@ PyObject* PyObjectFrom(const MT_Tuple2 &vec) { #ifdef USE_MATHUTILS float fvec[2]= {vec[0], vec[1]}; - return newVectorObject(fvec, 2, Py_WRAP); + return newVectorObject(fvec, 2, Py_WRAP, NULL); #else PyObject *list = PyList_New(2); PyList_SET_ITEM(list, 0, PyFloat_FromDouble(vec[0])); diff --git a/source/gameengine/Ketsji/KX_PyMath.h b/source/gameengine/Ketsji/KX_PyMath.h index f37925bb0ab..9ee11c9e745 100644 --- a/source/gameengine/Ketsji/KX_PyMath.h +++ b/source/gameengine/Ketsji/KX_PyMath.h @@ -31,12 +31,6 @@ #ifndef __KX_PYMATH_H__ #define __KX_PYMATH_H__ -#ifdef USE_MATHUTILS -extern "C" { -#include "../../blender/python/generic/Mathutils.h" /* so we can have mathutils callbacks */ -} -#endif - #include "MT_Point2.h" #include "MT_Point3.h" #include "MT_Vector2.h" @@ -48,6 +42,12 @@ extern "C" { #include "KX_Python.h" #include "PyObjectPlus.h" +#ifdef USE_MATHUTILS +extern "C" { +#include "../../blender/python/generic/Mathutils.h" /* so we can have mathutils callbacks */ +} +#endif + inline unsigned int Size(const MT_Matrix4x4&) { return 4; } inline unsigned int Size(const MT_Matrix3x3&) { return 3; } inline unsigned int Size(const MT_Tuple2&) { return 2; } @@ -154,7 +154,7 @@ bool PyVecTo(PyObject* pyval, T& vec) return true; } - else if (BGE_PROXY_CHECK_TYPE(pyval)) + else if (PyObject_TypeCheck(pyval, &PyObjectPlus::Type)) { /* note, include this check because PySequence_Check does too much introspection * on the PyObject (like getting its __class__, on a BGE type this means searching up * the parent list each time only to discover its not a sequence. diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index 736460d33db..eead7a51885 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -130,10 +130,10 @@ void KX_RasterizerDrawDebugLine(const MT_Vector3& from,const MT_Vector3& to,cons } /* Macro for building the keyboard translation */ -//#define KX_MACRO_addToDict(dict, name) PyDict_SetItemString(dict, #name, PyInt_FromLong(SCA_IInputDevice::KX_##name)) -#define KX_MACRO_addToDict(dict, name) PyDict_SetItemString(dict, #name, item=PyInt_FromLong(name)); Py_DECREF(item) +//#define KX_MACRO_addToDict(dict, name) PyDict_SetItemString(dict, #name, PyLong_FromSsize_t(SCA_IInputDevice::KX_##name)) +#define KX_MACRO_addToDict(dict, name) PyDict_SetItemString(dict, #name, item=PyLong_FromSsize_t(name)); Py_DECREF(item) /* For the defines for types from logic bricks, we do stuff explicitly... */ -#define KX_MACRO_addTypesToDict(dict, name, name2) PyDict_SetItemString(dict, #name, item=PyInt_FromLong(name2)); Py_DECREF(item) +#define KX_MACRO_addTypesToDict(dict, name, name2) PyDict_SetItemString(dict, #name, item=PyLong_FromSsize_t(name2)); Py_DECREF(item) // temporarily python stuff, will be put in another place later ! @@ -181,7 +181,7 @@ static PyObject* gPyExpandPath(PyObject*, PyObject* args) BLI_strncpy(expanded, filename, FILE_MAXDIR + FILE_MAXFILE); BLI_convertstringcode(expanded, gp_GamePythonPath); - return PyString_FromString(expanded); + return PyUnicode_FromString(expanded); } static char gPySendMessage_doc[] = @@ -306,7 +306,7 @@ static PyObject* gPySetMaxLogicFrame(PyObject*, PyObject* args) static PyObject* gPyGetMaxLogicFrame(PyObject*) { - return PyInt_FromLong(KX_KetsjiEngine::GetMaxLogicFrame()); + return PyLong_FromSsize_t(KX_KetsjiEngine::GetMaxLogicFrame()); } static PyObject* gPySetMaxPhysicsFrame(PyObject*, PyObject* args) @@ -321,7 +321,7 @@ static PyObject* gPySetMaxPhysicsFrame(PyObject*, PyObject* args) static PyObject* gPyGetMaxPhysicsFrame(PyObject*) { - return PyInt_FromLong(KX_KetsjiEngine::GetMaxPhysicsFrame()); + return PyLong_FromSsize_t(KX_KetsjiEngine::GetMaxPhysicsFrame()); } static PyObject* gPySetPhysicsTicRate(PyObject*, PyObject* args) @@ -386,7 +386,7 @@ static PyObject* gPyGetBlendFileList(PyObject*, PyObject* args) while ((dirp = readdir(dp)) != NULL) { if (BLI_testextensie(dirp->d_name, ".blend")) { - value = PyString_FromString(dirp->d_name); + value = PyUnicode_FromString(dirp->d_name); PyList_Append(list, value); Py_DECREF(value); } @@ -500,7 +500,7 @@ static PyObject *pyPrintExt(PyObject *,PyObject *,PyObject *) static PyObject *gEvalExpression(PyObject*, PyObject* value) { - char* txt= PyString_AsString(value); + char* txt= _PyUnicode_AsString(value); if (txt==NULL) { PyErr_SetString(PyExc_TypeError, "Expression.calc(text): expects a single string argument"); @@ -558,14 +558,14 @@ static struct PyMethodDef game_methods[] = { static PyObject* gPyGetWindowHeight(PyObject*, PyObject* args) { - return PyInt_FromLong((gp_Canvas ? gp_Canvas->GetHeight() : 0)); + return PyLong_FromSsize_t((gp_Canvas ? gp_Canvas->GetHeight() : 0)); } static PyObject* gPyGetWindowWidth(PyObject*, PyObject* args) { - return PyInt_FromLong((gp_Canvas ? gp_Canvas->GetWidth() : 0)); + return PyLong_FromSsize_t((gp_Canvas ? gp_Canvas->GetWidth() : 0)); } @@ -893,7 +893,7 @@ static PyObject* gPyGetGLSLMaterialSetting(PyObject*, } enabled = ((G.fileflags & flag) != 0); - return PyInt_FromLong(enabled); + return PyLong_FromSsize_t(enabled); } #define KX_TEXFACE_MATERIAL 0 @@ -937,7 +937,7 @@ static PyObject* gPyGetMaterialType(PyObject*) else flag = KX_TEXFACE_MATERIAL; - return PyInt_FromLong(flag); + return PyLong_FromSsize_t(flag); } static PyObject* gPyDrawLine(PyObject*, PyObject* args) @@ -1075,7 +1075,7 @@ PyObject* initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack PyDict_SetItemString(d, "globalDict", item=PyDict_New()); Py_DECREF(item); - ErrorObject = PyString_FromString("GameLogic.error"); + ErrorObject = PyUnicode_FromString("GameLogic.error"); PyDict_SetItemString(d, "error", ErrorObject); Py_DECREF(ErrorObject); @@ -1362,7 +1362,7 @@ PyObject *KXpy_import(PyObject *self, PyObject *args) /* check for builtin modules */ m = PyImport_AddModule("sys"); l = PyObject_GetAttrString(m, "builtin_module_names"); - n = PyString_FromString(name); + n = PyUnicode_FromString(name); if (PySequence_Contains(l, n)) { return PyImport_ImportModuleEx(name, globals, locals, fromlist); @@ -1538,7 +1538,7 @@ static void initPySysObjects__append(PyObject *sys_path, char *filename) BLI_split_dirfile_basic(filename, expanded, NULL); /* get the dir part of filename only */ BLI_convertstringcode(expanded, gp_GamePythonPath); /* filename from lib->filename is (always?) absolute, so this may not be needed but it wont hurt */ BLI_cleanup_file(gp_GamePythonPath, expanded); /* Dont use BLI_cleanup_dir because it adds a slash - BREAKS WIN32 ONLY */ - item= PyString_FromString(expanded); + item= PyUnicode_FromString(expanded); // printf("SysPath - '%s', '%s', '%s'\n", expanded, filename, gp_GamePythonPath); @@ -1735,7 +1735,7 @@ PyObject* initRasterizer(RAS_IRasterizer* rasty,RAS_ICanvas* canvas) // Add some symbolic constants to the module d = PyModule_GetDict(m); - ErrorObject = PyString_FromString("Rasterizer.error"); + ErrorObject = PyUnicode_FromString("Rasterizer.error"); PyDict_SetItemString(d, "error", ErrorObject); Py_DECREF(ErrorObject); @@ -1813,10 +1813,10 @@ static PyObject* gPyEventToCharacter(PyObject*, PyObject* args) if(IsPrintable(event)) { char ch[2] = {'\0', '\0'}; ch[0] = ToCharacter(event, (bool)shift); - return PyString_FromString(ch); + return PyUnicode_FromString(ch); } else { - return PyString_FromString(""); + return PyUnicode_FromString(""); } } @@ -2044,7 +2044,7 @@ int saveGamePythonConfig( char **marshal_buffer) char *marshal_cstring; #if PY_VERSION_HEX < 0x03000000 - marshal_cstring = PyString_AsString(pyGlobalDictMarshal); + marshal_cstring = _PyUnicode_AsString(pyGlobalDictMarshal); marshal_length= PyString_Size(pyGlobalDictMarshal); #else // py3 uses byte arrays marshal_cstring = PyBytes_AsString(pyGlobalDictMarshal); diff --git a/source/gameengine/Ketsji/KX_PythonInitTypes.cpp b/source/gameengine/Ketsji/KX_PythonInitTypes.cpp index d5d0fe3123c..8ff0bfd5379 100644 --- a/source/gameengine/Ketsji/KX_PythonInitTypes.cpp +++ b/source/gameengine/Ketsji/KX_PythonInitTypes.cpp @@ -87,69 +87,54 @@ #include "SCA_RandomActuator.h" #include "SCA_IController.h" - -void initPyObjectPlusType(PyTypeObject **parents) -{ - int i; - - for (i=0; parents[i]; i++) { - if(PyType_Ready(parents[i]) < 0) { - /* This is very very unlikely */ - printf("Error, pytype could not initialize, Blender may crash \"%s\"\n", parents[i]->tp_name); - return; - } - -#if 0 - PyObject_Print(reinterpret_castparents[i], stderr, 0); - fprintf(stderr, "\n"); - PyObject_Print(parents[i]->tp_dict, stderr, 0); - fprintf(stderr, "\n\n"); -#endif - - } - - PyObject *dict= NULL; - - while(i) { - i--; - - if (dict) { - PyDict_Update(parents[i]->tp_dict, dict); - } - dict= parents[i]->tp_dict; - -#if 1 - PyObject_Print(reinterpret_cast(parents[i]), stderr, 0); - fprintf(stderr, "\n"); - PyObject_Print(parents[i]->tp_dict, stderr, 0); - fprintf(stderr, "\n\n"); -#endif - - } -} - - - - -static void PyType_Ready_ADD(PyObject *dict, PyTypeObject *tp, PyAttributeDef *attributes) +static void PyType_Ready_ADD(PyObject *dict, PyTypeObject *tp, PyAttributeDef *attributes, int init_getset) { PyAttributeDef *attr; - PyObject *item; + + if(init_getset) { + /* we need to do this for all types before calling PyType_Ready + * since they will call the parents PyType_Ready and those might not have initialized vars yet */ + + //if(tp->tp_base==NULL) + // printf("Debug: No Parents - '%s'\n" , tp->tp_name); + + if(tp->tp_getset==NULL && attributes->m_name) { + PyGetSetDef *attr_getset; + int attr_tot= 0; + + for(attr= attributes; attr->m_name; attr++, attr_tot++) {}; + + tp->tp_getset = attr_getset = reinterpret_cast(PyMem_Malloc((attr_tot+1) * sizeof(PyGetSetDef))); // XXX - Todo, free + + + for(attr= attributes; attr->m_name; attr++, attr_getset++) { + attr_getset->name= (char *)attr->m_name; + attr_getset->doc= NULL; + + attr_getset->get= reinterpret_cast(PyObjectPlus::py_get_attrdef); + + if(attr->m_access==KX_PYATTRIBUTE_RO) + attr_getset->set= NULL; + else + attr_getset->set= reinterpret_cast(PyObjectPlus::py_set_attrdef); + + attr_getset->closure= reinterpret_cast(attr); + } + + memset(attr_getset, 0, sizeof(PyGetSetDef)); + } + } else { - PyType_Ready(tp); - PyDict_SetItemString(dict, tp->tp_name, reinterpret_cast(tp)); - - /* store attr defs in the tp_dict for to avoid string lookups */ - for(attr= attributes; attr->m_name; attr++) { - item= PyCObject_FromVoidPtr(attr, NULL); - PyDict_SetItemString(tp->tp_dict, attr->m_name, item); - Py_DECREF(item); + PyObject *item; + + PyType_Ready(tp); + PyDict_SetItemString(dict, tp->tp_name, reinterpret_cast(tp)); } } -#define PyType_Ready_Attr(d, n) PyType_Ready_ADD(d, &n::Type, n::Attributes) +#define PyType_Ready_Attr(d, n, i) PyType_Ready_ADD(d, &n::Type, n::Attributes, i) void initPyTypes(void) { @@ -165,70 +150,74 @@ void initPyTypes(void) PyDict_SetItemString(PySys_GetObject((char *)"modules"), (char *)"GameTypes", mod); Py_DECREF(mod); - PyType_Ready_Attr(dict, BL_ActionActuator); - PyType_Ready_Attr(dict, BL_Shader); - PyType_Ready_Attr(dict, BL_ShapeActionActuator); - PyType_Ready_Attr(dict, CListValue); - PyType_Ready_Attr(dict, CValue); - PyType_Ready_Attr(dict, KX_BlenderMaterial); - PyType_Ready_Attr(dict, KX_CDActuator); - PyType_Ready_Attr(dict, KX_Camera); - PyType_Ready_Attr(dict, KX_CameraActuator); - PyType_Ready_Attr(dict, KX_ConstraintActuator); - PyType_Ready_Attr(dict, KX_ConstraintWrapper); - PyType_Ready_Attr(dict, KX_GameActuator); - PyType_Ready_Attr(dict, KX_GameObject); - PyType_Ready_Attr(dict, KX_IpoActuator); - PyType_Ready_Attr(dict, KX_LightObject); - PyType_Ready_Attr(dict, KX_MeshProxy); - PyType_Ready_Attr(dict, KX_MouseFocusSensor); - PyType_Ready_Attr(dict, KX_NearSensor); - PyType_Ready_Attr(dict, KX_NetworkMessageActuator); - PyType_Ready_Attr(dict, KX_NetworkMessageSensor); - PyType_Ready_Attr(dict, KX_ObjectActuator); - PyType_Ready_Attr(dict, KX_ParentActuator); - PyType_Ready_Attr(dict, KX_PhysicsObjectWrapper); - PyType_Ready_Attr(dict, KX_PolyProxy); - PyType_Ready_Attr(dict, KX_PolygonMaterial); - PyType_Ready_Attr(dict, KX_RadarSensor); - PyType_Ready_Attr(dict, KX_RaySensor); - PyType_Ready_Attr(dict, KX_SCA_AddObjectActuator); - PyType_Ready_Attr(dict, KX_SCA_DynamicActuator); - PyType_Ready_Attr(dict, KX_SCA_EndObjectActuator); - PyType_Ready_Attr(dict, KX_SCA_ReplaceMeshActuator); - PyType_Ready_Attr(dict, KX_Scene); - PyType_Ready_Attr(dict, KX_SceneActuator); - PyType_Ready_Attr(dict, KX_SoundActuator); - PyType_Ready_Attr(dict, KX_StateActuator); - PyType_Ready_Attr(dict, KX_TouchSensor); - PyType_Ready_Attr(dict, KX_TrackToActuator); - PyType_Ready_Attr(dict, KX_VehicleWrapper); - PyType_Ready_Attr(dict, KX_VertexProxy); - PyType_Ready_Attr(dict, KX_VisibilityActuator); - PyType_Ready_Attr(dict, PyObjectPlus); - PyType_Ready_Attr(dict, SCA_2DFilterActuator); - PyType_Ready_Attr(dict, SCA_ANDController); - PyType_Ready_Attr(dict, SCA_ActuatorSensor); - PyType_Ready_Attr(dict, SCA_AlwaysSensor); - PyType_Ready_Attr(dict, SCA_DelaySensor); - PyType_Ready_Attr(dict, SCA_ILogicBrick); - PyType_Ready_Attr(dict, SCA_IObject); - PyType_Ready_Attr(dict, SCA_ISensor); - PyType_Ready_Attr(dict, SCA_JoystickSensor); - PyType_Ready_Attr(dict, SCA_KeyboardSensor); - PyType_Ready_Attr(dict, SCA_MouseSensor); - PyType_Ready_Attr(dict, SCA_NANDController); - PyType_Ready_Attr(dict, SCA_NORController); - PyType_Ready_Attr(dict, SCA_ORController); - PyType_Ready_Attr(dict, SCA_PropertyActuator); - PyType_Ready_Attr(dict, SCA_PropertySensor); - PyType_Ready_Attr(dict, SCA_PythonController); - PyType_Ready_Attr(dict, SCA_RandomActuator); - PyType_Ready_Attr(dict, SCA_RandomSensor); - PyType_Ready_Attr(dict, SCA_XNORController); - PyType_Ready_Attr(dict, SCA_XORController); - PyType_Ready_Attr(dict, SCA_IController); + for(int init_getset= 1; init_getset > -1; init_getset--) { /* run twice, once to init the getsets another to run PyType_Ready */ + PyType_Ready_Attr(dict, BL_ActionActuator, init_getset); + PyType_Ready_Attr(dict, BL_Shader, init_getset); + PyType_Ready_Attr(dict, BL_ShapeActionActuator, init_getset); + PyType_Ready_Attr(dict, CListValue, init_getset); + PyType_Ready_Attr(dict, CValue, init_getset); + PyType_Ready_Attr(dict, KX_BlenderMaterial, init_getset); + PyType_Ready_Attr(dict, KX_CDActuator, init_getset); + PyType_Ready_Attr(dict, KX_Camera, init_getset); + PyType_Ready_Attr(dict, KX_CameraActuator, init_getset); + PyType_Ready_Attr(dict, KX_ConstraintActuator, init_getset); + PyType_Ready_Attr(dict, KX_ConstraintWrapper, init_getset); + PyType_Ready_Attr(dict, KX_GameActuator, init_getset); + PyType_Ready_Attr(dict, KX_GameObject, init_getset); + PyType_Ready_Attr(dict, KX_IpoActuator, init_getset); + PyType_Ready_Attr(dict, KX_LightObject, init_getset); + PyType_Ready_Attr(dict, KX_MeshProxy, init_getset); + PyType_Ready_Attr(dict, KX_MouseFocusSensor, init_getset); + PyType_Ready_Attr(dict, KX_NearSensor, init_getset); + PyType_Ready_Attr(dict, KX_NetworkMessageActuator, init_getset); + PyType_Ready_Attr(dict, KX_NetworkMessageSensor, init_getset); + PyType_Ready_Attr(dict, KX_ObjectActuator, init_getset); + PyType_Ready_Attr(dict, KX_ParentActuator, init_getset); + PyType_Ready_Attr(dict, KX_PhysicsObjectWrapper, init_getset); + PyType_Ready_Attr(dict, KX_PolyProxy, init_getset); + PyType_Ready_Attr(dict, KX_PolygonMaterial, init_getset); + PyType_Ready_Attr(dict, KX_RadarSensor, init_getset); + PyType_Ready_Attr(dict, KX_RaySensor, init_getset); + PyType_Ready_Attr(dict, KX_SCA_AddObjectActuator, init_getset); + PyType_Ready_Attr(dict, KX_SCA_DynamicActuator, init_getset); + PyType_Ready_Attr(dict, KX_SCA_EndObjectActuator, init_getset); + PyType_Ready_Attr(dict, KX_SCA_ReplaceMeshActuator, init_getset); + PyType_Ready_Attr(dict, KX_Scene, init_getset); + PyType_Ready_Attr(dict, KX_SceneActuator, init_getset); + PyType_Ready_Attr(dict, KX_SoundActuator, init_getset); + PyType_Ready_Attr(dict, KX_StateActuator, init_getset); + PyType_Ready_Attr(dict, KX_TouchSensor, init_getset); + PyType_Ready_Attr(dict, KX_TrackToActuator, init_getset); + PyType_Ready_Attr(dict, KX_VehicleWrapper, init_getset); + PyType_Ready_Attr(dict, KX_VertexProxy, init_getset); + PyType_Ready_Attr(dict, KX_VisibilityActuator, init_getset); + PyType_Ready_Attr(dict, PyObjectPlus, init_getset); + PyType_Ready_Attr(dict, SCA_2DFilterActuator, init_getset); + PyType_Ready_Attr(dict, SCA_ANDController, init_getset); + PyType_Ready_Attr(dict, SCA_ActuatorSensor, init_getset); + PyType_Ready_Attr(dict, SCA_AlwaysSensor, init_getset); + PyType_Ready_Attr(dict, SCA_DelaySensor, init_getset); + PyType_Ready_Attr(dict, SCA_ILogicBrick, init_getset); + PyType_Ready_Attr(dict, SCA_IObject, init_getset); + PyType_Ready_Attr(dict, SCA_ISensor, init_getset); + PyType_Ready_Attr(dict, SCA_JoystickSensor, init_getset); + PyType_Ready_Attr(dict, SCA_KeyboardSensor, init_getset); + PyType_Ready_Attr(dict, SCA_MouseSensor, init_getset); + PyType_Ready_Attr(dict, SCA_NANDController, init_getset); + PyType_Ready_Attr(dict, SCA_NORController, init_getset); + PyType_Ready_Attr(dict, SCA_ORController, init_getset); + PyType_Ready_Attr(dict, SCA_PropertyActuator, init_getset); + PyType_Ready_Attr(dict, SCA_PropertySensor, init_getset); + PyType_Ready_Attr(dict, SCA_PythonController, init_getset); + PyType_Ready_Attr(dict, SCA_RandomActuator, init_getset); + PyType_Ready_Attr(dict, SCA_RandomSensor, init_getset); + PyType_Ready_Attr(dict, SCA_XNORController, init_getset); + PyType_Ready_Attr(dict, SCA_XORController, init_getset); + PyType_Ready_Attr(dict, SCA_IController, init_getset); + } + + /* Normal python type */ PyType_Ready(&KX_PythonSeq_Type); diff --git a/source/gameengine/Ketsji/KX_PythonSeq.cpp b/source/gameengine/Ketsji/KX_PythonSeq.cpp index cc8021fc2e4..5b4d77156db 100644 --- a/source/gameengine/Ketsji/KX_PythonSeq.cpp +++ b/source/gameengine/Ketsji/KX_PythonSeq.cpp @@ -57,7 +57,7 @@ static Py_ssize_t KX_PythonSeq_len( PyObject * self ) PyObjectPlus *self_plus= BGE_PROXY_REF(((KX_PythonSeq *)self)->base); if(self_plus==NULL) { - PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG); + PyErr_SetString(PyExc_SystemError, "len(seq): "BGE_PROXY_ERROR_MSG); return -1; } @@ -84,7 +84,7 @@ static PyObject *KX_PythonSeq_getIndex(PyObject* self, int index) PyObjectPlus *self_plus= BGE_PROXY_REF(((KX_PythonSeq *)self)->base); if(self_plus==NULL) { - PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG); + PyErr_SetString(PyExc_SystemError, "val = seq[i]: "BGE_PROXY_ERROR_MSG); return NULL; } @@ -145,25 +145,9 @@ static PyObject *KX_PythonSeq_getIndex(PyObject* self, int index) return NULL; } - -static PyObject * KX_PythonSeq_subscript(PyObject * self, PyObject *key) +static PyObjectPlus * KX_PythonSeq_subscript__internal(PyObject *self, char *key) { PyObjectPlus *self_plus= BGE_PROXY_REF(((KX_PythonSeq *)self)->base); - char *name = NULL; - - if(self_plus==NULL) { - PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG); - return NULL; - } - - if (PyInt_Check(key)) { - return KX_PythonSeq_getIndex(self, PyInt_AS_LONG( key )); - } else if ( PyString_Check(key) ) { - name = PyString_AsString( key ); - } else { - PyErr_SetString( PyExc_TypeError, "expected a string or an index" ); - return NULL; - } switch(((KX_PythonSeq *)self)->type) { case KX_PYGENSEQ_CONT_TYPE_SENSORS: @@ -172,8 +156,9 @@ static PyObject * KX_PythonSeq_subscript(PyObject * self, PyObject *key) SCA_ISensor* sensor; for (unsigned int index=0;indexGetName() == name) - return sensor->GetProxy(); + if (sensor->GetName() == key) + return static_cast(sensor); + } break; } @@ -183,8 +168,8 @@ static PyObject * KX_PythonSeq_subscript(PyObject * self, PyObject *key) SCA_IActuator* actuator; for (unsigned int index=0;indexGetName() == name) - return actuator->GetProxy(); + if (actuator->GetName() == key) + return static_cast(actuator); } break; } @@ -194,8 +179,8 @@ static PyObject * KX_PythonSeq_subscript(PyObject * self, PyObject *key) SCA_ISensor *sensor; for (unsigned int index=0;indexGetName() == name) - return sensor->GetProxy(); + if (sensor->GetName() == key) + return static_cast(sensor); } break; } @@ -205,8 +190,8 @@ static PyObject * KX_PythonSeq_subscript(PyObject * self, PyObject *key) SCA_IController *controller; for (unsigned int index=0;indexGetName() == name) - return controller->GetProxy(); + if (controller->GetName() == key) + return static_cast(controller); } break; } @@ -216,23 +201,105 @@ static PyObject * KX_PythonSeq_subscript(PyObject * self, PyObject *key) SCA_IActuator *actuator; for (unsigned int index=0;indexGetName() == name) - return actuator->GetProxy(); + if (actuator->GetName() == key) + return static_cast(actuator); } break; } } - PyErr_Format( PyExc_KeyError, "requested item \"%s\" does not exist", name); return NULL; } + +static PyObject * KX_PythonSeq_subscript(PyObject * self, PyObject *key) +{ + PyObjectPlus *self_plus= BGE_PROXY_REF(((KX_PythonSeq *)self)->base); + + if(self_plus==NULL) { + PyErr_SetString(PyExc_SystemError, "val = seq[key], KX_PythonSeq: "BGE_PROXY_ERROR_MSG); + return NULL; + } + + if (PyLong_Check(key)) { + return KX_PythonSeq_getIndex(self, PyLong_AsSsize_t( key )); + } + else if ( PyUnicode_Check(key) ) { + char *name = _PyUnicode_AsString(key); + PyObjectPlus *ret = KX_PythonSeq_subscript__internal(self, name); + + if(ret) { + return ret->GetProxy(); + } else { + PyErr_Format( PyExc_KeyError, "requested item \"%s\" does not exist", name); + return NULL; + } + } + else { + PyErr_SetString( PyExc_TypeError, "expected a string or an index" ); + return NULL; + } +} + + +static int KX_PythonSeq_contains(PyObject *self, PyObject *key) +{ + PyObjectPlus *self_plus= BGE_PROXY_REF(((KX_PythonSeq *)self)->base); + + if(self_plus==NULL) { + PyErr_SetString(PyExc_SystemError, "key in seq, KX_PythonSeq: "BGE_PROXY_ERROR_MSG); + return -1; + } + if(!PyUnicode_Check(key)) { + PyErr_SetString(PyExc_SystemError, "key in seq, KX_PythonSeq: key must be a string"); + return -1; + } + + if(KX_PythonSeq_subscript__internal(self, _PyUnicode_AsString(key))) + return 1; + + return 0; +} + +/* Matches python dict.get(key, [default]) */ +PyObject* KX_PythonSeq_get(PyObject * self, PyObject *args) +{ + char *key; + PyObject* def = Py_None; + PyObjectPlus* ret_plus; + + if (!PyArg_ParseTuple(args, "s|O:get", &key, &def)) + return NULL; + + if((ret_plus = KX_PythonSeq_subscript__internal(self, key))) + return ret_plus->GetProxy(); + + Py_INCREF(def); + return def; +} + +PySequenceMethods KX_PythonSeq_as_sequence = { + NULL, /* Cant set the len otherwise it can evaluate as false */ + NULL, /* sq_concat */ + NULL, /* sq_repeat */ + NULL, /* sq_item */ + NULL, /* sq_slice */ + NULL, /* sq_ass_item */ + NULL, /* sq_ass_slice */ + (objobjproc)KX_PythonSeq_contains, /* sq_contains */ +}; + static PyMappingMethods KX_PythonSeq_as_mapping = { KX_PythonSeq_len, /* mp_length */ KX_PythonSeq_subscript, /* mp_subscript */ 0, /* mp_ass_subscript */ }; +PyMethodDef KX_PythonSeq_methods[] = { + // dict style access for props + {"get",(PyCFunction) KX_PythonSeq_get, METH_VARARGS}, + {NULL,NULL} //Sentinel +}; /* * Initialize the interator index @@ -241,7 +308,7 @@ static PyMappingMethods KX_PythonSeq_as_mapping = { static PyObject *KX_PythonSeq_getIter(KX_PythonSeq *self) { if(BGE_PROXY_REF(self->base)==NULL) { - PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG); + PyErr_SetString(PyExc_SystemError, "for i in seq: "BGE_PROXY_ERROR_MSG); return NULL; } @@ -313,13 +380,17 @@ PyTypeObject KX_PythonSeq_Type = { NULL, /* printfunc tp_print; */ NULL, /* getattrfunc tp_getattr; */ NULL, /* setattrfunc tp_setattr; */ +#if PY_VERSION_HEX >= 0x03000000 // TODO - richcmp + NULL, +#else ( cmpfunc ) KX_PythonSeq_compare, /* cmpfunc tp_compare; */ +#endif ( reprfunc ) KX_PythonSeq_repr, /* reprfunc tp_repr; */ /* Method suites for standard classes */ NULL, /* PyNumberMethods *tp_as_number; */ - NULL, /* PySequenceMethods *tp_as_sequence; */ + &KX_PythonSeq_as_sequence, /* PySequenceMethods *tp_as_sequence; */ &KX_PythonSeq_as_mapping, /* PyMappingMethods *tp_as_mapping; */ /* More standard operations (here for binary compatibility) */ @@ -357,7 +428,7 @@ PyTypeObject KX_PythonSeq_Type = { ( iternextfunc ) KX_PythonSeq_nextIter, /* iternextfunc tp_iternext; */ /*** Attribute descriptor and subclassing stuff ***/ - NULL, /* struct PyMethodDef *tp_methods; */ + KX_PythonSeq_methods, /* struct PyMethodDef *tp_methods; */ NULL, /* struct PyMemberDef *tp_members; */ NULL, /* struct PyGetSetDef *tp_getset; */ NULL, /* struct _typeobject *tp_base; */ diff --git a/source/gameengine/Ketsji/KX_RadarSensor.cpp b/source/gameengine/Ketsji/KX_RadarSensor.cpp index 064dc9126ac..e39d3756b71 100644 --- a/source/gameengine/Ketsji/KX_RadarSensor.cpp +++ b/source/gameengine/Ketsji/KX_RadarSensor.cpp @@ -49,8 +49,7 @@ KX_RadarSensor::KX_RadarSensor(SCA_EventManager* eventmgr, double resetmargin, bool bFindMaterial, const STR_String& touchedpropname, - class KX_Scene* kxscene, - PyTypeObject* T) + class KX_Scene* kxscene) : KX_NearSensor( eventmgr, @@ -61,8 +60,8 @@ KX_RadarSensor::KX_RadarSensor(SCA_EventManager* eventmgr, bFindMaterial, touchedpropname, kxscene, - physCtrl, - T), + physCtrl), + m_coneradius(coneradius), m_coneheight(coneheight), m_axis(axis) @@ -245,21 +244,15 @@ PyTypeObject KX_RadarSensor::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject KX_RadarSensor::Parents[] = { - &KX_RadarSensor::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &KX_NearSensor::Type, - &KX_TouchSensor::Type, - &SCA_ISensor::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef KX_RadarSensor::Methods[] = { @@ -283,16 +276,3 @@ PyAttributeDef KX_RadarSensor::Attributes[] = { {NULL} //Sentinel }; -PyObject* KX_RadarSensor::py_getattro(PyObject *attr) -{ - py_getattro_up(KX_NearSensor); -} - -PyObject* KX_RadarSensor::py_getattro_dict() { - py_getattro_dict_up(KX_NearSensor); -} - -int KX_RadarSensor::py_setattro(PyObject *attr, PyObject* value) -{ - py_setattro_up(KX_NearSensor); -} diff --git a/source/gameengine/Ketsji/KX_RadarSensor.h b/source/gameengine/Ketsji/KX_RadarSensor.h index 2e5a0e68bed..344be0e399f 100644 --- a/source/gameengine/Ketsji/KX_RadarSensor.h +++ b/source/gameengine/Ketsji/KX_RadarSensor.h @@ -70,8 +70,7 @@ public: double resetmargin, bool bFindMaterial, const STR_String& touchedpropname, - class KX_Scene* kxscene, - PyTypeObject* T = &Type); + class KX_Scene* kxscene); KX_RadarSensor(); virtual ~KX_RadarSensor(); virtual void SynchronizeTransform(); @@ -89,9 +88,7 @@ public: KX_RADAR_AXIS_NEG_Z }; - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject* value); + /* python */ virtual sensortype GetSensorType() { return ST_RADAR; } //Deprecated -----> diff --git a/source/gameengine/Ketsji/KX_RaySensor.cpp b/source/gameengine/Ketsji/KX_RaySensor.cpp index 78a61e9d95e..3f27496df71 100644 --- a/source/gameengine/Ketsji/KX_RaySensor.cpp +++ b/source/gameengine/Ketsji/KX_RaySensor.cpp @@ -55,9 +55,8 @@ KX_RaySensor::KX_RaySensor(class SCA_EventManager* eventmgr, bool bXRay, double distance, int axis, - KX_Scene* ketsjiScene, - PyTypeObject* T) - : SCA_ISensor(gameobj,eventmgr, T), + KX_Scene* ketsjiScene) + : SCA_ISensor(gameobj,eventmgr), m_propertyname(propname), m_bFindMaterial(bFindMaterial), m_bXRay(bXRay), @@ -336,20 +335,16 @@ PyTypeObject KX_RaySensor::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods - -}; - -PyParentObject KX_RaySensor::Parents[] = { - &KX_RaySensor::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_ISensor::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new + }; PyMethodDef KX_RaySensor::Methods[] = { @@ -447,18 +442,4 @@ PyObject* KX_RaySensor::PyGetHitNormal() return retVal; } - - -PyObject* KX_RaySensor::py_getattro(PyObject *attr) { - py_getattro_up(SCA_ISensor); -} - -PyObject* KX_RaySensor::py_getattro_dict() { - py_getattro_dict_up(SCA_ISensor); -} - -int KX_RaySensor::py_setattro(PyObject *attr, PyObject *value) { - py_setattro_up(SCA_ISensor); -} - // <----- Deprecated diff --git a/source/gameengine/Ketsji/KX_RaySensor.h b/source/gameengine/Ketsji/KX_RaySensor.h index 9efb046742f..530c8ce54e5 100644 --- a/source/gameengine/Ketsji/KX_RaySensor.h +++ b/source/gameengine/Ketsji/KX_RaySensor.h @@ -62,8 +62,7 @@ public: bool bXRay, double distance, int axis, - class KX_Scene* ketsjiScene, - PyTypeObject* T = &Type); + class KX_Scene* ketsjiScene); virtual ~KX_RaySensor(); virtual CValue* GetReplica(); @@ -84,11 +83,6 @@ public: KX_RAY_AXIS_NEG_Y, KX_RAY_AXIS_NEG_Z }; - - - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); // Deprecated -----> KX_PYMETHOD_DOC_NOARGS(KX_RaySensor,GetHitObject); diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp index 75435b97797..239c4a0be67 100644 --- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp @@ -55,10 +55,9 @@ KX_SCA_AddObjectActuator::KX_SCA_AddObjectActuator(SCA_IObject *gameobj, const float *linvel, bool linv_local, const float *angvel, - bool angv_local, - PyTypeObject* T) + bool angv_local) : - SCA_IActuator(gameobj, T), + SCA_IActuator(gameobj), m_OriginalObject(original), m_scene(scene), @@ -187,20 +186,17 @@ PyTypeObject KX_SCA_AddObjectActuator::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, + &SCA_IActuator::Type, + 0,0,0,0,0,0, + py_base_new }; -PyParentObject KX_SCA_AddObjectActuator::Parents[] = { - &KX_SCA_AddObjectActuator::Type, - &SCA_IActuator::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL -}; PyMethodDef KX_SCA_AddObjectActuator::Methods[] = { // ---> deprecated {"setTime", (PyCFunction) KX_SCA_AddObjectActuator::sPySetTime, METH_O, (PY_METHODCHAR)SetTime_doc}, @@ -263,21 +259,6 @@ PyObject* KX_SCA_AddObjectActuator::pyattr_get_objectLastCreated(void *self, con return actuator->m_lastCreatedObject->GetProxy(); } - -PyObject* KX_SCA_AddObjectActuator::py_getattro(PyObject *attr) -{ - py_getattro_up(SCA_IActuator); -} - -PyObject* KX_SCA_AddObjectActuator::py_getattro_dict() { - py_getattro_dict_up(SCA_IActuator); -} - -int KX_SCA_AddObjectActuator::py_setattro(PyObject *attr, PyObject* value) -{ - py_setattro_up(SCA_IActuator); -} - /* 1. setObject */ const char KX_SCA_AddObjectActuator::SetObject_doc[] = "setObject(object)\n" @@ -316,7 +297,7 @@ const char KX_SCA_AddObjectActuator::SetTime_doc[] = PyObject* KX_SCA_AddObjectActuator::PySetTime(PyObject* value) { ShowDeprecationWarning("setTime()", "the time property"); - int deltatime = PyInt_AsLong(value); + int deltatime = PyLong_AsSsize_t(value); if (deltatime==-1 && PyErr_Occurred()) { PyErr_SetString(PyExc_TypeError, "expected an int"); return NULL; @@ -339,7 +320,7 @@ const char KX_SCA_AddObjectActuator::GetTime_doc[] = PyObject* KX_SCA_AddObjectActuator::PyGetTime() { ShowDeprecationWarning("getTime()", "the time property"); - return PyInt_FromLong(m_timeProp); + return PyLong_FromSsize_t(m_timeProp); } @@ -361,7 +342,7 @@ PyObject* KX_SCA_AddObjectActuator::PyGetObject(PyObject* args) Py_RETURN_NONE; if (ret_name_only) - return PyString_FromString(m_OriginalObject->GetName().ReadPtr()); + return PyUnicode_FromString(m_OriginalObject->GetName().ReadPtr()); else return m_OriginalObject->GetProxy(); } diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h index 6746b7d1bc6..3151e7a89ca 100644 --- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h +++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h @@ -88,8 +88,7 @@ public: const float *linvel, bool linv_local, const float *angvel, - bool angv_local, - PyTypeObject* T=&Type + bool angv_local ); ~KX_SCA_AddObjectActuator(void); @@ -110,10 +109,6 @@ public: virtual bool Update(); - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject* value); - SCA_IObject* GetLastCreatedObject( ) const ; diff --git a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp index a50764a54e6..423fd0db7f2 100644 --- a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp @@ -47,9 +47,7 @@ /* Integration hooks ------------------------------------------------------- */ - PyTypeObject - -KX_SCA_DynamicActuator::Type = { +PyTypeObject KX_SCA_DynamicActuator::Type = { #if (PY_VERSION_HEX >= 0x02060000) PyVarObject_HEAD_INIT(NULL, 0) #else @@ -66,22 +64,17 @@ KX_SCA_DynamicActuator::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject KX_SCA_DynamicActuator::Parents[] = { - &KX_SCA_DynamicActuator::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IActuator::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; - PyMethodDef KX_SCA_DynamicActuator::Methods[] = { // ---> deprecated KX_PYMETHODTABLE(KX_SCA_DynamicActuator, setOperation), @@ -96,21 +89,6 @@ PyAttributeDef KX_SCA_DynamicActuator::Attributes[] = { }; -PyObject* KX_SCA_DynamicActuator::py_getattro(PyObject *attr) -{ - py_getattro_up(SCA_IActuator); -} - -PyObject* KX_SCA_DynamicActuator::py_getattro_dict() { - py_getattro_dict_up(SCA_IActuator); -} - -int KX_SCA_DynamicActuator::py_setattro(PyObject *attr, PyObject* value) -{ - py_setattro_up(SCA_IActuator); -} - - /* 1. setOperation */ KX_PYMETHODDEF_DOC(KX_SCA_DynamicActuator, setOperation, "setOperation(operation?)\n" @@ -142,7 +120,7 @@ KX_PYMETHODDEF_DOC(KX_SCA_DynamicActuator, getOperation, ) { ShowDeprecationWarning("getOperation()", "the mode property"); - return PyInt_FromLong((long)m_dyn_operation); + return PyLong_FromSsize_t((long)m_dyn_operation); } @@ -152,10 +130,9 @@ KX_PYMETHODDEF_DOC(KX_SCA_DynamicActuator, getOperation, KX_SCA_DynamicActuator::KX_SCA_DynamicActuator(SCA_IObject *gameobj, short dyn_operation, - float setmass, - PyTypeObject* T) : + float setmass) : - SCA_IActuator(gameobj, T), + SCA_IActuator(gameobj), m_dyn_operation(dyn_operation), m_setmass(setmass) { diff --git a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.h b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.h index 4add707f8cd..8b598c9ecfa 100644 --- a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.h +++ b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.h @@ -50,8 +50,7 @@ class KX_SCA_DynamicActuator : public SCA_IActuator KX_SCA_DynamicActuator( SCA_IObject* gameobj, short dyn_operation, - float setmass, - PyTypeObject* T=&Type + float setmass ); ~KX_SCA_DynamicActuator( @@ -73,11 +72,6 @@ class KX_SCA_DynamicActuator : public SCA_IActuator KX_DYN_SET_MASS, }; - - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); - /* 1. setOperation */ KX_PYMETHOD_DOC(KX_SCA_DynamicActuator,setOperation); KX_PYMETHOD_DOC(KX_SCA_DynamicActuator,getOperation); diff --git a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp index 728254e7f48..47c5c3aeeeb 100644 --- a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp @@ -43,9 +43,8 @@ #endif KX_SCA_EndObjectActuator::KX_SCA_EndObjectActuator(SCA_IObject *gameobj, - SCA_IScene* scene, - PyTypeObject* T): - SCA_IActuator(gameobj, T), + SCA_IScene* scene): + SCA_IActuator(gameobj), m_scene(scene) { // intentionally empty @@ -108,24 +107,17 @@ PyTypeObject KX_SCA_EndObjectActuator::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - - -PyParentObject KX_SCA_EndObjectActuator::Parents[] = { - &KX_SCA_EndObjectActuator::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IActuator::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; - - PyMethodDef KX_SCA_EndObjectActuator::Methods[] = { {NULL,NULL} //Sentinel }; @@ -134,13 +126,4 @@ PyAttributeDef KX_SCA_EndObjectActuator::Attributes[] = { { NULL } //Sentinel }; -PyObject* KX_SCA_EndObjectActuator::py_getattro(PyObject *attr) -{ - py_getattro_up(SCA_IActuator); -} - -PyObject* KX_SCA_EndObjectActuator::py_getattro_dict() { - py_getattro_dict_up(SCA_IActuator); -} - /* eof */ diff --git a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.h b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.h index 70d72f1f8da..782a24b1ef1 100644 --- a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.h +++ b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.h @@ -47,8 +47,7 @@ class KX_SCA_EndObjectActuator : public SCA_IActuator public: KX_SCA_EndObjectActuator( SCA_IObject* gameobj, - SCA_IScene* scene, - PyTypeObject* T=&Type + SCA_IScene* scene ); ~KX_SCA_EndObjectActuator(); @@ -63,9 +62,6 @@ class KX_SCA_EndObjectActuator : public SCA_IActuator /* --------------------------------------------------------------------- */ /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); }; /* end of class KX_EditObjectActuator : public SCA_PropertyActuator */ diff --git a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp index 00842d7012a..2884bb76565 100644 --- a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp @@ -50,9 +50,7 @@ /* Integration hooks ------------------------------------------------------- */ - PyTypeObject - -KX_SCA_ReplaceMeshActuator::Type = { +PyTypeObject KX_SCA_ReplaceMeshActuator::Type = { #if (PY_VERSION_HEX >= 0x02060000) PyVarObject_HEAD_INIT(NULL, 0) #else @@ -69,23 +67,17 @@ KX_SCA_ReplaceMeshActuator::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject KX_SCA_ReplaceMeshActuator::Parents[] = { - &KX_SCA_ReplaceMeshActuator::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IActuator::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; - - PyMethodDef KX_SCA_ReplaceMeshActuator::Methods[] = { KX_PYMETHODTABLE(KX_SCA_ReplaceMeshActuator, instantReplaceMesh), // Deprecated -----> @@ -99,20 +91,6 @@ PyAttributeDef KX_SCA_ReplaceMeshActuator::Attributes[] = { { NULL } //Sentinel }; -PyObject* KX_SCA_ReplaceMeshActuator::py_getattro(PyObject *attr) -{ - py_getattro_up(SCA_IActuator); -} - -PyObject* KX_SCA_ReplaceMeshActuator::py_getattro_dict() { - py_getattro_dict_up(SCA_IActuator); -} - -int KX_SCA_ReplaceMeshActuator::py_setattro(PyObject *attr, PyObject* value) -{ - py_setattro_up(SCA_IActuator); -} - PyObject* KX_SCA_ReplaceMeshActuator::pyattr_get_mesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) { KX_SCA_ReplaceMeshActuator* actuator = static_cast(self); @@ -161,7 +139,7 @@ KX_PYMETHODDEF_DOC(KX_SCA_ReplaceMeshActuator, getMesh, if (!m_mesh) Py_RETURN_NONE; - return PyString_FromString(const_cast(m_mesh->GetName().ReadPtr())); + return PyUnicode_FromString(const_cast(m_mesh->GetName().ReadPtr())); } @@ -178,10 +156,9 @@ KX_PYMETHODDEF_DOC(KX_SCA_ReplaceMeshActuator, instantReplaceMesh, KX_SCA_ReplaceMeshActuator::KX_SCA_ReplaceMeshActuator(SCA_IObject *gameobj, class RAS_MeshObject *mesh, - SCA_IScene* scene, - PyTypeObject* T) : + SCA_IScene* scene) : - SCA_IActuator(gameobj, T), + SCA_IActuator(gameobj), m_mesh(mesh), m_scene(scene) { diff --git a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h index 0e7f7852701..6a68bd88cc5 100644 --- a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h +++ b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h @@ -55,9 +55,7 @@ class KX_SCA_ReplaceMeshActuator : public SCA_IActuator KX_SCA_ReplaceMeshActuator( SCA_IObject* gameobj, RAS_MeshObject *mesh, - SCA_IScene* scene, - PyTypeObject* T=&Type - ); + SCA_IScene* scene); ~KX_SCA_ReplaceMeshActuator( ); @@ -71,10 +69,7 @@ class KX_SCA_ReplaceMeshActuator : public SCA_IActuator void InstantReplaceMesh(); - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject* value); - + /* python api */ static PyObject* pyattr_get_mesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_mesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index c0d8a7090c4..51f5276e075 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -138,7 +138,7 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice, class SND_IAudioDevice* adi, const STR_String& sceneName, Scene *scene): - PyObjectPlus(&KX_Scene::Type), + PyObjectPlus(), m_keyboardmgr(NULL), m_mousemgr(NULL), m_sceneConverter(NULL), @@ -1629,17 +1629,15 @@ PyTypeObject KX_Scene::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject KX_Scene::Parents[] = { - &KX_Scene::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef KX_Scene::Methods[] = { @@ -1654,7 +1652,7 @@ PyMethodDef KX_Scene::Methods[] = { PyObject* KX_Scene::pyattr_get_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_Scene* self= static_cast(self_v); - return PyString_FromString(self->GetName().ReadPtr()); + return PyUnicode_FromString(self->GetName().ReadPtr()); } PyObject* KX_Scene::pyattr_get_objects(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) @@ -1730,72 +1728,6 @@ PyAttributeDef KX_Scene::Attributes[] = { { NULL } //Sentinel }; -PyObject* KX_Scene::py_getattro__internal(PyObject *attr) -{ - py_getattro_up(PyObjectPlus); -} - -int KX_Scene::py_setattro__internal(PyObject *attr, PyObject *value) -{ - py_setattro_up(PyObjectPlus); -} - -PyObject* KX_Scene::py_getattro(PyObject *attr) -{ - PyObject *object = py_getattro__internal(attr); - - if (object==NULL) - { - PyErr_Clear(); - object = PyDict_GetItem(m_attr_dict, attr); - if(object) { - Py_INCREF(object); - } - else { - PyErr_Format(PyExc_AttributeError, "value = scene.myAttr: KX_Scene, attribute \"%s\" not found", PyString_AsString(attr)); - } - } - - return object; -} - -PyObject* KX_Scene::py_getattro_dict() { - //py_getattro_dict_up(PyObjectPlus); - - PyObject *dict= py_getattr_dict(PyObjectPlus::py_getattro_dict(), Type.tp_dict); - if(dict==NULL) - return NULL; - - /* normally just return this but KX_Scene has some more items */ - - PyDict_Update(dict, m_attr_dict); - return dict; -} - -int KX_Scene::py_setattro(PyObject *attr, PyObject *value) -{ - int ret= py_setattro__internal(attr, value); - - if (ret==PY_SET_ATTR_MISSING) { - if (PyDict_SetItem(m_attr_dict, attr, value)==0) { - PyErr_Clear(); - ret= PY_SET_ATTR_SUCCESS; - } - else { - PyErr_SetString(PyExc_AttributeError, "scene.UserAttr = value: KX_Scenes, failed assigning value to internal dictionary"); - ret= PY_SET_ATTR_FAIL; - } - } - - return ret; -} - -int KX_Scene::py_delattro(PyObject *attr) -{ - PyDict_DelItem(m_attr_dict, attr); - return 0; -} - KX_PYMETHODDEF_DOC_NOARGS(KX_Scene, getLightList, "getLightList() -> list [KX_Light]\n" "Returns a list of all lights in the scene.\n" @@ -1820,7 +1752,7 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_Scene, getName, ) { ShowDeprecationWarning("getName()", "the name property"); - return PyString_FromString(GetName()); + return PyUnicode_FromString(GetName()); } KX_PYMETHODDEF_DOC(KX_Scene, addObject, diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h index 79d3f7fd828..2792f1f5fe4 100644 --- a/source/gameengine/Ketsji/KX_Scene.h +++ b/source/gameengine/Ketsji/KX_Scene.h @@ -563,15 +563,7 @@ public: static PyObject* pyattr_get_active_camera(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_active_camera(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); - virtual PyObject* py_getattro(PyObject *attr); /* name, active_camera, gravity, suspended, viewport, framing, activity_culling, activity_culling_radius */ - virtual PyObject* py_getattro_dict(); - - virtual int py_setattro(PyObject *attr, PyObject *value); - virtual int py_delattro(PyObject *attr); - virtual PyObject* py_repr(void) { return PyString_FromString(GetName().ReadPtr()); } - - PyObject* py_getattro__internal(PyObject *attr); - int py_setattro__internal(PyObject *attr, PyObject *pyvalue); + virtual PyObject* py_repr(void) { return PyUnicode_FromString(GetName().ReadPtr()); } /** * Sets the time the scene was suspended diff --git a/source/gameengine/Ketsji/KX_SceneActuator.cpp b/source/gameengine/Ketsji/KX_SceneActuator.cpp index 1b790ec9824..5528e58ef77 100644 --- a/source/gameengine/Ketsji/KX_SceneActuator.cpp +++ b/source/gameengine/Ketsji/KX_SceneActuator.cpp @@ -49,9 +49,8 @@ KX_SceneActuator::KX_SceneActuator(SCA_IObject *gameobj, KX_Scene *scene, KX_KetsjiEngine* ketsjiEngine, const STR_String& nextSceneName, - KX_Camera* camera, - PyTypeObject* T) - : SCA_IActuator(gameobj, T) + KX_Camera* camera) + : SCA_IActuator(gameobj) { m_mode = mode; m_scene = scene; @@ -134,7 +133,7 @@ bool KX_SceneActuator::Update() { // if no camera is set and the parent object is a camera, use it as the camera SCA_IObject* parent = GetParent(); - if (parent->isA(&KX_Camera::Type)) + if (parent->GetGameObjectType()==SCA_IObject::OBJ_CAMERA) { m_scene->SetActiveCamera((KX_Camera*)parent); } @@ -239,26 +238,17 @@ PyTypeObject KX_SceneActuator::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - - - -PyParentObject KX_SceneActuator::Parents[] = -{ - &KX_SceneActuator::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IActuator::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; - - PyMethodDef KX_SceneActuator::Methods[] = { //Deprecated functions ------> @@ -280,20 +270,6 @@ PyAttributeDef KX_SceneActuator::Attributes[] = { { NULL } //Sentinel }; -PyObject* KX_SceneActuator::py_getattro(PyObject *attr) -{ - py_getattro_up(SCA_IActuator); -} - -PyObject* KX_SceneActuator::py_getattro_dict() { - py_getattro_dict_up(SCA_IActuator); -} - -int KX_SceneActuator::py_setattro(PyObject *attr, PyObject *value) -{ - py_setattro_up(SCA_IActuator); -} - PyObject* KX_SceneActuator::pyattr_get_camera(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) { KX_SceneActuator* actuator = static_cast(self); @@ -355,7 +331,7 @@ const char KX_SceneActuator::GetUseRestart_doc[] = PyObject* KX_SceneActuator::PyGetUseRestart() { ShowDeprecationWarning("getUseRestart()", "the useRestart property"); - return PyInt_FromLong(!(m_restart == 0)); + return PyLong_FromSsize_t(!(m_restart == 0)); } @@ -391,7 +367,7 @@ const char KX_SceneActuator::GetScene_doc[] = PyObject* KX_SceneActuator::PyGetScene() { ShowDeprecationWarning("getScene()", "the scene property"); - return PyString_FromString(m_nextSceneName); + return PyUnicode_FromString(m_nextSceneName); } @@ -432,7 +408,7 @@ PyObject* KX_SceneActuator::PyGetCamera() { ShowDeprecationWarning("getCamera()", "the camera property"); if (m_camera) { - return PyString_FromString(m_camera->GetName()); + return PyUnicode_FromString(m_camera->GetName()); } else { Py_RETURN_NONE; diff --git a/source/gameengine/Ketsji/KX_SceneActuator.h b/source/gameengine/Ketsji/KX_SceneActuator.h index 2412dd02590..86de3395d1e 100644 --- a/source/gameengine/Ketsji/KX_SceneActuator.h +++ b/source/gameengine/Ketsji/KX_SceneActuator.h @@ -77,8 +77,7 @@ class KX_SceneActuator : public SCA_IActuator KX_Scene* scene, KX_KetsjiEngine* ketsjiEngine, const STR_String& nextSceneName, - KX_Camera* camera, - PyTypeObject* T=&Type); + KX_Camera* camera); virtual ~KX_SceneActuator(); virtual CValue* GetReplica(); @@ -92,10 +91,6 @@ class KX_SceneActuator : public SCA_IActuator /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); - /* 1. set */ /* Removed */ diff --git a/source/gameengine/Ketsji/KX_SoundActuator.cpp b/source/gameengine/Ketsji/KX_SoundActuator.cpp index c13271f66a5..673f42283dd 100644 --- a/source/gameengine/Ketsji/KX_SoundActuator.cpp +++ b/source/gameengine/Ketsji/KX_SoundActuator.cpp @@ -50,9 +50,8 @@ KX_SoundActuator::KX_SoundActuator(SCA_IObject* gameobj, SND_Scene* sndscene, KX_SOUNDACT_TYPE type, short start, - short end, - PyTypeObject* T) - : SCA_IActuator(gameobj,T) + short end) + : SCA_IActuator(gameobj) { m_soundObject = sndobj; m_soundScene = sndscene; @@ -250,25 +249,17 @@ PyTypeObject KX_SoundActuator::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - - - -PyParentObject KX_SoundActuator::Parents[] = { - &KX_SoundActuator::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IActuator::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; - - PyMethodDef KX_SoundActuator::Methods[] = { // Deprecated -----> {"setFilename", (PyCFunction) KX_SoundActuator::sPySetFilename, METH_VARARGS,NULL}, @@ -340,25 +331,13 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_SoundActuator, stopSound, } /* Atribute setting and getting -------------------------------------------- */ -PyObject* KX_SoundActuator::py_getattro(PyObject *attr) -{ - py_getattro_up(SCA_IActuator); -} - -PyObject* KX_SoundActuator::py_getattro_dict() { - py_getattro_dict_up(SCA_IActuator); -} - -int KX_SoundActuator::py_setattro(PyObject *attr, PyObject* value) { - py_setattro_up(SCA_IActuator); -} PyObject* KX_SoundActuator::pyattr_get_filename(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) { KX_SoundActuator * actuator = static_cast (self); if (!actuator->m_soundObject) { - return PyString_FromString(""); + return PyUnicode_FromString(""); } STR_String objectname = actuator->m_soundObject->GetObjectName(); char* name = objectname.Ptr(); @@ -367,7 +346,7 @@ PyObject* KX_SoundActuator::pyattr_get_filename(void *self, const struct KX_PYAT PyErr_SetString(PyExc_RuntimeError, "value = actuator.fileName: KX_SoundActuator, unable to get sound fileName"); return NULL; } else - return PyString_FromString(name); + return PyUnicode_FromString(name); } PyObject* KX_SoundActuator::pyattr_get_gain(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) @@ -402,7 +381,7 @@ PyObject* KX_SoundActuator::pyattr_get_looping(void *self, const struct KX_PYATT { KX_SoundActuator * actuator = static_cast (self); int looping = (actuator->m_soundObject) ? actuator->m_soundObject->GetLoopMode() : (int)SND_LOOP_OFF; - PyObject* result = PyInt_FromLong(looping); + PyObject* result = PyLong_FromSsize_t(looping); return result; } @@ -580,7 +559,7 @@ PyObject* KX_SoundActuator::PyGetFilename() ShowDeprecationWarning("getFilename()", "the fileName property"); if (!m_soundObject) { - return PyString_FromString(""); + return PyUnicode_FromString(""); } STR_String objectname = m_soundObject->GetObjectName(); char* name = objectname.Ptr(); @@ -589,7 +568,7 @@ PyObject* KX_SoundActuator::PyGetFilename() PyErr_SetString(PyExc_RuntimeError, "Unable to get sound fileName"); return NULL; } else - return PyString_FromString(name); + return PyUnicode_FromString(name); } PyObject* KX_SoundActuator::PySetGain(PyObject* args) @@ -689,7 +668,7 @@ PyObject* KX_SoundActuator::PyGetLooping() { ShowDeprecationWarning("getLooping()", "the looping property"); int looping = (m_soundObject) ? m_soundObject->GetLoopMode() : (int)SND_LOOP_OFF; - PyObject* result = PyInt_FromLong(looping); + PyObject* result = PyLong_FromSsize_t(looping); return result; } @@ -777,7 +756,7 @@ PyObject* KX_SoundActuator::PySetType(PyObject* args) PyObject* KX_SoundActuator::PyGetType() { ShowDeprecationWarning("getType()", "the mode property"); - return PyInt_FromLong(m_type); + return PyLong_FromSsize_t(m_type); } // <----- diff --git a/source/gameengine/Ketsji/KX_SoundActuator.h b/source/gameengine/Ketsji/KX_SoundActuator.h index a7491355667..adafee0a30b 100644 --- a/source/gameengine/Ketsji/KX_SoundActuator.h +++ b/source/gameengine/Ketsji/KX_SoundActuator.h @@ -66,8 +66,7 @@ public: class SND_Scene* sndscene, KX_SOUNDACT_TYPE type, short start, - short end, - PyTypeObject* T=&Type); + short end); ~KX_SoundActuator(); @@ -81,10 +80,6 @@ public: /* Python interface --------------------------------------------------- */ /* -------------------------------------------------------------------- */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject* value); - KX_PYMETHOD_DOC_NOARGS(KX_SoundActuator, startSound); KX_PYMETHOD_DOC_NOARGS(KX_SoundActuator, pauseSound); KX_PYMETHOD_DOC_NOARGS(KX_SoundActuator, stopSound); diff --git a/source/gameengine/Ketsji/KX_StateActuator.cpp b/source/gameengine/Ketsji/KX_StateActuator.cpp index f6979eee0f4..9815d6274aa 100644 --- a/source/gameengine/Ketsji/KX_StateActuator.cpp +++ b/source/gameengine/Ketsji/KX_StateActuator.cpp @@ -38,10 +38,9 @@ KX_StateActuator::KX_StateActuator( SCA_IObject* gameobj, int operation, - unsigned int mask, - PyTypeObject* T + unsigned int mask ) - : SCA_IActuator(gameobj,T), + : SCA_IActuator(gameobj), m_operation(operation), m_mask(mask) { @@ -154,24 +153,18 @@ PyTypeObject KX_StateActuator::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject -KX_StateActuator::Parents[] = { - &KX_StateActuator::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IActuator::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; -PyMethodDef -KX_StateActuator::Methods[] = { +PyMethodDef KX_StateActuator::Methods[] = { // deprecated --> {"setOperation", (PyCFunction) KX_StateActuator::sPySetOperation, METH_VARARGS, (PY_METHODCHAR)SetOperation_doc}, @@ -187,20 +180,6 @@ PyAttributeDef KX_StateActuator::Attributes[] = { { NULL } //Sentinel }; -PyObject* KX_StateActuator::py_getattro(PyObject *attr) -{ - py_getattro_up(SCA_IActuator); -} - -PyObject* KX_StateActuator::py_getattro_dict() { - py_getattro_dict_up(SCA_IActuator); -} - -int KX_StateActuator::py_setattro(PyObject *attr, PyObject* value) -{ - py_setattro_up(SCA_IActuator); -} - /* set operation ---------------------------------------------------------- */ const char diff --git a/source/gameengine/Ketsji/KX_StateActuator.h b/source/gameengine/Ketsji/KX_StateActuator.h index a4191a4c5fd..ce86c4b44fe 100644 --- a/source/gameengine/Ketsji/KX_StateActuator.h +++ b/source/gameengine/Ketsji/KX_StateActuator.h @@ -66,9 +66,8 @@ class KX_StateActuator : public SCA_IActuator KX_StateActuator( SCA_IObject* gameobj, int operation, - unsigned int mask, - PyTypeObject* T=&Type - ); + unsigned int mask + ); virtual ~KX_StateActuator( @@ -89,10 +88,6 @@ class KX_StateActuator : public SCA_IActuator /* --------------------------------------------------------------------- */ /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject* value); //KX_PYMETHOD_DOC KX_PYMETHOD_DOC_VARARGS(KX_StateActuator,SetOperation); KX_PYMETHOD_DOC_VARARGS(KX_StateActuator,SetMask); diff --git a/source/gameengine/Ketsji/KX_TouchSensor.cpp b/source/gameengine/Ketsji/KX_TouchSensor.cpp index c06acd4a873..b0cf172c27a 100644 --- a/source/gameengine/Ketsji/KX_TouchSensor.cpp +++ b/source/gameengine/Ketsji/KX_TouchSensor.cpp @@ -97,8 +97,8 @@ bool KX_TouchSensor::Evaluate() return result; } -KX_TouchSensor::KX_TouchSensor(SCA_EventManager* eventmgr,KX_GameObject* gameobj,bool bFindMaterial,bool bTouchPulse,const STR_String& touchedpropname,PyTypeObject* T) -:SCA_ISensor(gameobj,eventmgr,T), +KX_TouchSensor::KX_TouchSensor(SCA_EventManager* eventmgr,KX_GameObject* gameobj,bool bFindMaterial,bool bTouchPulse,const STR_String& touchedpropname) +:SCA_ISensor(gameobj,eventmgr), m_touchedpropname(touchedpropname), m_bFindMaterial(bFindMaterial), m_bTouchPulse(bTouchPulse), @@ -310,19 +310,15 @@ PyTypeObject KX_TouchSensor::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject KX_TouchSensor::Parents[] = { - &KX_TouchSensor::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_ISensor::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef KX_TouchSensor::Methods[] = { @@ -348,20 +344,6 @@ PyAttributeDef KX_TouchSensor::Attributes[] = { { NULL } //Sentinel }; -PyObject* KX_TouchSensor::py_getattro(PyObject *attr) -{ - py_getattro_up(SCA_ISensor); -} - -PyObject* KX_TouchSensor::py_getattro_dict() { - py_getattro_dict_up(SCA_ISensor); -} - -int KX_TouchSensor::py_setattro(PyObject *attr, PyObject *value) -{ - py_setattro_up(SCA_ISensor); -} - /* Python API */ /* 1. setProperty */ @@ -374,7 +356,7 @@ const char KX_TouchSensor::SetProperty_doc[] = PyObject* KX_TouchSensor::PySetProperty(PyObject* value) { ShowDeprecationWarning("setProperty()", "the propName property"); - char *nameArg= PyString_AsString(value); + char *nameArg= _PyUnicode_AsString(value); if (nameArg==NULL) { PyErr_SetString(PyExc_ValueError, "expected a "); return NULL; @@ -392,7 +374,7 @@ const char KX_TouchSensor::GetProperty_doc[] = PyObject* KX_TouchSensor::PyGetProperty() { ShowDeprecationWarning("getProperty()", "the propName property"); - return PyString_FromString(m_touchedpropname); + return PyUnicode_FromString(m_touchedpropname); } const char KX_TouchSensor::GetHitObject_doc[] = @@ -433,7 +415,7 @@ const char KX_TouchSensor::GetTouchMaterial_doc[] = PyObject* KX_TouchSensor::PyGetTouchMaterial() { ShowDeprecationWarning("getTouchMaterial()", "the useMaterial property"); - return PyInt_FromLong(m_bFindMaterial); + return PyLong_FromSsize_t(m_bFindMaterial); } /* 6. setTouchMaterial */ @@ -446,7 +428,7 @@ const char KX_TouchSensor::SetTouchMaterial_doc[] = PyObject* KX_TouchSensor::PySetTouchMaterial(PyObject *value) { ShowDeprecationWarning("setTouchMaterial()", "the useMaterial property"); - int pulseArg = PyInt_AsLong(value); + int pulseArg = PyLong_AsSsize_t(value); if(pulseArg ==-1 && PyErr_Occurred()) { PyErr_SetString(PyExc_ValueError, "expected a bool"); diff --git a/source/gameengine/Ketsji/KX_TouchSensor.h b/source/gameengine/Ketsji/KX_TouchSensor.h index 476c63e89db..6cbf5b15e3b 100644 --- a/source/gameengine/Ketsji/KX_TouchSensor.h +++ b/source/gameengine/Ketsji/KX_TouchSensor.h @@ -79,8 +79,7 @@ public: class KX_GameObject* gameobj, bool bFindMaterial, bool bTouchPulse, - const STR_String& touchedpropname, - PyTypeObject* T=&Type) ; + const STR_String& touchedpropname) ; virtual ~KX_TouchSensor(); virtual CValue* GetReplica(); @@ -121,10 +120,6 @@ public: /* --------------------------------------------------------------------- */ /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); //Deprecated -----> /* 1. setProperty */ diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.cpp b/source/gameengine/Ketsji/KX_TrackToActuator.cpp index 5a50d0fb944..e8a06d8d619 100644 --- a/source/gameengine/Ketsji/KX_TrackToActuator.cpp +++ b/source/gameengine/Ketsji/KX_TrackToActuator.cpp @@ -59,10 +59,8 @@ KX_TrackToActuator::KX_TrackToActuator(SCA_IObject *gameobj, int time, bool allow3D, int trackflag, - int upflag, - PyTypeObject* T) - : - SCA_IActuator(gameobj, T) + int upflag) + : SCA_IActuator(gameobj) { m_time = time; m_allow3D = allow3D; @@ -74,7 +72,6 @@ KX_TrackToActuator::KX_TrackToActuator(SCA_IObject *gameobj, if (m_object) m_object->RegisterActuator(this); - if (gameobj->isA(&KX_GameObject::Type)) { // if the object is vertex parented, don't check parent orientation as the link is broken if (!((KX_GameObject*)gameobj)->IsVertexParent()){ @@ -450,25 +447,17 @@ PyTypeObject KX_TrackToActuator::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, + &SCA_IActuator::Type, + 0,0,0,0,0,0, + py_base_new }; - - -PyParentObject KX_TrackToActuator::Parents[] = { - &KX_TrackToActuator::Type, - &SCA_IActuator::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL -}; - - - PyMethodDef KX_TrackToActuator::Methods[] = { // ---> deprecated {"setTime", (PyCFunction) KX_TrackToActuator::sPySetTime, METH_VARARGS, (PY_METHODCHAR)SetTime_doc}, @@ -518,20 +507,6 @@ int KX_TrackToActuator::pyattr_set_object(void *self, const struct KX_PYATTRIBUT } -PyObject* KX_TrackToActuator::py_getattro(PyObject *attr) -{ - py_getattro_up(SCA_IActuator); -} - -PyObject* KX_TrackToActuator::py_getattro_dict() { - py_getattro_dict_up(SCA_IActuator); -} - -int KX_TrackToActuator::py_setattro(PyObject *attr, PyObject* value) -{ - py_setattro_up(SCA_IActuator); -} - /* 1. setObject */ const char KX_TrackToActuator::SetObject_doc[] = "setObject(object)\n" @@ -576,7 +551,7 @@ PyObject* KX_TrackToActuator::PyGetObject(PyObject* args) Py_RETURN_NONE; if (ret_name_only) - return PyString_FromString(m_object->GetName()); + return PyUnicode_FromString(m_object->GetName()); else return m_object->GetProxy(); } @@ -613,7 +588,7 @@ const char KX_TrackToActuator::GetTime_doc[] = PyObject* KX_TrackToActuator::PyGetTime() { ShowDeprecationWarning("getTime()", "the timer property"); - return PyInt_FromLong(m_time); + return PyLong_FromSsize_t(m_time); } @@ -625,7 +600,7 @@ const char KX_TrackToActuator::GetUse3D_doc[] = PyObject* KX_TrackToActuator::PyGetUse3D() { ShowDeprecationWarning("setTime()", "the use3D property"); - return PyInt_FromLong(!(m_allow3D == 0)); + return PyLong_FromSsize_t(!(m_allow3D == 0)); } diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.h b/source/gameengine/Ketsji/KX_TrackToActuator.h index c4cc2b1f062..801e695bb9b 100644 --- a/source/gameengine/Ketsji/KX_TrackToActuator.h +++ b/source/gameengine/Ketsji/KX_TrackToActuator.h @@ -56,7 +56,7 @@ class KX_TrackToActuator : public SCA_IActuator public: KX_TrackToActuator(SCA_IObject* gameobj, SCA_IObject *ob, int time, - bool threedee,int trackflag,int upflag, PyTypeObject* T=&Type); + bool threedee,int trackflag,int upflag); virtual ~KX_TrackToActuator(); virtual CValue* GetReplica() { KX_TrackToActuator* replica = new KX_TrackToActuator(*this); @@ -70,9 +70,6 @@ class KX_TrackToActuator : public SCA_IActuator virtual bool Update(double curtime, bool frame); /* Python part */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject* value); /* These are used to get and set m_ob */ static PyObject* pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); diff --git a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp index 8146d04a878..7001bfc8b7e 100644 --- a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp +++ b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp @@ -16,8 +16,8 @@ KX_VehicleWrapper::KX_VehicleWrapper( PHY_IVehicle* vehicle, - PHY_IPhysicsEnvironment* physenv,PyTypeObject *T) : - PyObjectPlus(T), + PHY_IPhysicsEnvironment* physenv) : + PyObjectPlus(), m_vehicle(vehicle), m_physenv(physenv) { @@ -127,13 +127,13 @@ PyObject* KX_VehicleWrapper::PyGetWheelOrientationQuaternion(PyObject* args) PyObject* KX_VehicleWrapper::PyGetNumWheels(PyObject* args) { - return PyInt_FromLong(m_vehicle->GetNumWheels()); + return PyLong_FromSsize_t(m_vehicle->GetNumWheels()); } PyObject* KX_VehicleWrapper::PyGetConstraintId(PyObject* args) { - return PyInt_FromLong(m_vehicle->GetUserConstraintId()); + return PyLong_FromSsize_t(m_vehicle->GetUserConstraintId()); } @@ -264,7 +264,7 @@ PyObject* KX_VehicleWrapper::PySetSteeringValue(PyObject* args) PyObject* KX_VehicleWrapper::PyGetConstraintType(PyObject* args) { - return PyInt_FromLong(m_vehicle->GetUserConstraintType()); + return PyLong_FromSsize_t(m_vehicle->GetUserConstraintType()); } @@ -289,35 +289,17 @@ PyTypeObject KX_VehicleWrapper::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, + &PyObjectPlus::Type, + 0,0,0,0,0,0, + py_base_new }; -PyParentObject KX_VehicleWrapper::Parents[] = { - &KX_VehicleWrapper::Type, - &PyObjectPlus::Type, - NULL -}; - -PyObject* KX_VehicleWrapper::py_getattro(PyObject *attr) -{ - //here you can search for existing data members (like mass,friction etc.) - py_getattro_up(PyObjectPlus); -} - -PyObject* KX_VehicleWrapper::py_getattro_dict() { - py_getattro_dict_up(PyObjectPlus); -} - -int KX_VehicleWrapper::py_setattro(PyObject *attr,PyObject* value) -{ - py_setattro_up(PyObjectPlus); -}; - - PyMethodDef KX_VehicleWrapper::Methods[] = { {"addWheel",(PyCFunction) KX_VehicleWrapper::sPyAddWheel, METH_VARARGS}, {"getNumWheels",(PyCFunction) KX_VehicleWrapper::sPyGetNumWheels, METH_VARARGS}, diff --git a/source/gameengine/Ketsji/KX_VehicleWrapper.h b/source/gameengine/Ketsji/KX_VehicleWrapper.h index c2b5e3d9251..d7f2da5cd7c 100644 --- a/source/gameengine/Ketsji/KX_VehicleWrapper.h +++ b/source/gameengine/Ketsji/KX_VehicleWrapper.h @@ -12,14 +12,11 @@ class PHY_IMotionState; class KX_VehicleWrapper : public PyObjectPlus { Py_Header; - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); std::vector m_motionStates; public: - KX_VehicleWrapper(PHY_IVehicle* vehicle,class PHY_IPhysicsEnvironment* physenv,PyTypeObject *T = &Type); + KX_VehicleWrapper(PHY_IVehicle* vehicle,class PHY_IPhysicsEnvironment* physenv); virtual ~KX_VehicleWrapper (); int getConstraintId(); diff --git a/source/gameengine/Ketsji/KX_VertexProxy.cpp b/source/gameengine/Ketsji/KX_VertexProxy.cpp index 4b0ad083473..cb8c891969d 100644 --- a/source/gameengine/Ketsji/KX_VertexProxy.cpp +++ b/source/gameengine/Ketsji/KX_VertexProxy.cpp @@ -53,18 +53,15 @@ PyTypeObject KX_VertexProxy::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject KX_VertexProxy::Parents[] = { - &KX_VertexProxy::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &CValue::Type, - &PyObjectPlus::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef KX_VertexProxy::Methods[] = { @@ -85,37 +82,38 @@ PyMethodDef KX_VertexProxy::Methods[] = { PyAttributeDef KX_VertexProxy::Attributes[] = { //KX_PYATTRIBUTE_TODO("DummyProps"), - + KX_PYATTRIBUTE_DUMMY("x"), KX_PYATTRIBUTE_DUMMY("y"), KX_PYATTRIBUTE_DUMMY("z"), - + KX_PYATTRIBUTE_DUMMY("r"), KX_PYATTRIBUTE_DUMMY("g"), KX_PYATTRIBUTE_DUMMY("b"), KX_PYATTRIBUTE_DUMMY("a"), - + KX_PYATTRIBUTE_DUMMY("u"), KX_PYATTRIBUTE_DUMMY("v"), - + KX_PYATTRIBUTE_DUMMY("u2"), KX_PYATTRIBUTE_DUMMY("v2"), - + KX_PYATTRIBUTE_DUMMY("XYZ"), KX_PYATTRIBUTE_DUMMY("UV"), - + KX_PYATTRIBUTE_DUMMY("color"), KX_PYATTRIBUTE_DUMMY("colour"), - + KX_PYATTRIBUTE_DUMMY("normal"), - + { NULL } //Sentinel }; +#if 0 PyObject* KX_VertexProxy::py_getattro(PyObject *attr) { - char *attr_str= PyString_AsString(attr); + char *attr_str= _PyUnicode_AsString(attr); if (attr_str[1]=='\0') { // Group single letters // pos if (attr_str[0]=='x') @@ -141,8 +139,8 @@ KX_VertexProxy::py_getattro(PyObject *attr) if (attr_str[0]=='v') return PyFloat_FromDouble(m_vertex->getUV1()[1]); } - - + + if (!strcmp(attr_str, "XYZ")) return PyObjectFrom(MT_Vector3(m_vertex->getXYZ())); @@ -156,22 +154,21 @@ KX_VertexProxy::py_getattro(PyObject *attr) color /= 255.0; return PyObjectFrom(color); } - + if (!strcmp(attr_str, "normal")) { return PyObjectFrom(MT_Vector3(m_vertex->getNormal())); } - + py_getattro_up(CValue); } +#endif -PyObject* KX_VertexProxy::py_getattro_dict() { - py_getattro_dict_up(CValue); -} +#if 0 int KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue) { - char *attr_str= PyString_AsString(attr); + char *attr_str= _PyUnicode_AsString(attr); if (PySequence_Check(pyvalue)) { if (!strcmp(attr_str, "XYZ")) @@ -185,7 +182,7 @@ int KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue) } return PY_SET_ATTR_FAIL; } - + if (!strcmp(attr_str, "UV")) { MT_Point2 vec; @@ -197,7 +194,7 @@ int KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue) } return PY_SET_ATTR_FAIL; } - + if (!strcmp(attr_str, "color") || !strcmp(attr_str, "colour")) { MT_Vector4 vec; @@ -209,7 +206,7 @@ int KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue) } return PY_SET_ATTR_FAIL; } - + if (!strcmp(attr_str, "normal")) { MT_Vector3 vec; @@ -222,7 +219,7 @@ int KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue) return PY_SET_ATTR_FAIL; } } - + if (PyFloat_Check(pyvalue)) { float val = PyFloat_AsDouble(pyvalue); @@ -235,7 +232,7 @@ int KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue) m_mesh->SetMeshModified(true); return PY_SET_ATTR_SUCCESS; } - + if (!strcmp(attr_str, "y")) { pos.y() = val; @@ -243,7 +240,7 @@ int KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue) m_mesh->SetMeshModified(true); return PY_SET_ATTR_SUCCESS; } - + if (!strcmp(attr_str, "z")) { pos.z() = val; @@ -251,7 +248,7 @@ int KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue) m_mesh->SetMeshModified(true); return PY_SET_ATTR_SUCCESS; } - + // uv MT_Point2 uv = m_vertex->getUV1(); if (!strcmp(attr_str, "u")) @@ -287,7 +284,7 @@ int KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue) m_mesh->SetMeshModified(true); return PY_SET_ATTR_SUCCESS; } - + // col unsigned int icol = *((const unsigned int *)m_vertex->getRGBA()); unsigned char *cp = (unsigned char*) &icol; @@ -321,9 +318,10 @@ int KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue) return PY_SET_ATTR_SUCCESS; } } - + return CValue::py_setattro(attr, pyvalue); } +#endif KX_VertexProxy::KX_VertexProxy(KX_MeshProxy*mesh, RAS_TexVert* vertex) : m_vertex(vertex), @@ -339,7 +337,7 @@ KX_VertexProxy::~KX_VertexProxy() // stuff for cvalue related things CValue* KX_VertexProxy::Calc(VALUE_OPERATOR, CValue *) { return NULL;} -CValue* KX_VertexProxy::CalcFinal(VALUE_DATA_TYPE, VALUE_OPERATOR, CValue *) { return NULL;} +CValue* KX_VertexProxy::CalcFinal(VALUE_DATA_TYPE, VALUE_OPERATOR, CValue *) { return NULL;} STR_String sVertexName="vertex"; const STR_String & KX_VertexProxy::GetText() {return sVertexName;}; double KX_VertexProxy::GetNumber() { return -1;} @@ -348,7 +346,7 @@ void KX_VertexProxy::SetName(const char *) { }; CValue* KX_VertexProxy::GetReplica() { return NULL;} // stuff for python integration - + PyObject* KX_VertexProxy::PyGetXYZ() { return PyObjectFrom(MT_Point3(m_vertex->getXYZ())); @@ -359,7 +357,7 @@ PyObject* KX_VertexProxy::PySetXYZ(PyObject* value) MT_Point3 vec; if (!PyVecTo(value, vec)) return NULL; - + m_vertex->SetXYZ(vec); m_mesh->SetMeshModified(true); Py_RETURN_NONE; @@ -375,7 +373,7 @@ PyObject* KX_VertexProxy::PySetNormal(PyObject* value) MT_Vector3 vec; if (!PyVecTo(value, vec)) return NULL; - + m_vertex->SetNormal(vec); m_mesh->SetMeshModified(true); Py_RETURN_NONE; @@ -385,18 +383,18 @@ PyObject* KX_VertexProxy::PySetNormal(PyObject* value) PyObject* KX_VertexProxy::PyGetRGBA() { int *rgba = (int *) m_vertex->getRGBA(); - return PyInt_FromLong(*rgba); + return PyLong_FromSsize_t(*rgba); } PyObject* KX_VertexProxy::PySetRGBA(PyObject* value) { - if PyInt_Check(value) { - int rgba = PyInt_AsLong(value); + if PyLong_Check(value) { + int rgba = PyLong_AsSsize_t(value); m_vertex->SetRGBA(rgba); m_mesh->SetMeshModified(true); Py_RETURN_NONE; } - else { + else { MT_Vector4 vec; if (PyVecTo(value, vec)) { @@ -405,7 +403,7 @@ PyObject* KX_VertexProxy::PySetRGBA(PyObject* value) Py_RETURN_NONE; } } - + PyErr_SetString(PyExc_TypeError, "vert.setRGBA(value): KX_VertexProxy, expected a 4D vector or an int"); return NULL; } @@ -421,7 +419,7 @@ PyObject* KX_VertexProxy::PySetUV(PyObject* value) MT_Point2 vec; if (!PyVecTo(value, vec)) return NULL; - + m_vertex->SetUV(vec); m_mesh->SetMeshModified(true); Py_RETURN_NONE; @@ -436,14 +434,14 @@ PyObject* KX_VertexProxy::PySetUV2(PyObject* args) { MT_Point2 vec; unsigned int unit= RAS_TexVert::SECOND_UV; - + PyObject* list= NULL; if(!PyArg_ParseTuple(args, "O|i:setUV2", &list, &unit)) return NULL; - + if (!PyVecTo(list, vec)) return NULL; - + m_vertex->SetFlag((m_vertex->getFlag()|RAS_TexVert::SECOND_UV)); m_vertex->SetUnit(unit); m_vertex->SetUV2(vec); diff --git a/source/gameengine/Ketsji/KX_VertexProxy.h b/source/gameengine/Ketsji/KX_VertexProxy.h index 42db5fbc322..13c57e9f556 100644 --- a/source/gameengine/Ketsji/KX_VertexProxy.h +++ b/source/gameengine/Ketsji/KX_VertexProxy.h @@ -53,9 +53,6 @@ public: // stuff for python integration - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *pyvalue); KX_PYMETHOD_NOARGS(KX_VertexProxy,GetXYZ); KX_PYMETHOD_O(KX_VertexProxy,SetXYZ); diff --git a/source/gameengine/Ketsji/KX_VisibilityActuator.cpp b/source/gameengine/Ketsji/KX_VisibilityActuator.cpp index d848065ad73..3561ccde9d9 100644 --- a/source/gameengine/Ketsji/KX_VisibilityActuator.cpp +++ b/source/gameengine/Ketsji/KX_VisibilityActuator.cpp @@ -39,10 +39,9 @@ KX_VisibilityActuator::KX_VisibilityActuator( SCA_IObject* gameobj, bool visible, bool occlusion, - bool recursive, - PyTypeObject* T + bool recursive ) - : SCA_IActuator(gameobj,T), + : SCA_IActuator(gameobj), m_visible(visible), m_occlusion(occlusion), m_recursive(recursive) @@ -108,25 +107,18 @@ PyTypeObject KX_VisibilityActuator::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods - -}; - -PyParentObject -KX_VisibilityActuator::Parents[] = { - &KX_VisibilityActuator::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IActuator::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; -PyMethodDef -KX_VisibilityActuator::Methods[] = { +PyMethodDef KX_VisibilityActuator::Methods[] = { // Deprecated -----> {"set", (PyCFunction) KX_VisibilityActuator::sPySetVisible, METH_VARARGS, (PY_METHODCHAR) SetVisible_doc}, @@ -141,21 +133,6 @@ PyAttributeDef KX_VisibilityActuator::Attributes[] = { { NULL } //Sentinel }; -PyObject* KX_VisibilityActuator::py_getattro(PyObject *attr) -{ - py_getattro_up(SCA_IActuator); -} - -PyObject* KX_VisibilityActuator::py_getattro_dict() { - py_getattro_dict_up(SCA_IActuator); -} - -int KX_VisibilityActuator::py_setattro(PyObject *attr, PyObject *value) -{ - py_setattro_up(SCA_IActuator); -} - - /* set visibility ---------------------------------------------------------- */ const char KX_VisibilityActuator::SetVisible_doc[] = diff --git a/source/gameengine/Ketsji/KX_VisibilityActuator.h b/source/gameengine/Ketsji/KX_VisibilityActuator.h index 45aba50f645..3ad50c6cea2 100644 --- a/source/gameengine/Ketsji/KX_VisibilityActuator.h +++ b/source/gameengine/Ketsji/KX_VisibilityActuator.h @@ -48,9 +48,7 @@ class KX_VisibilityActuator : public SCA_IActuator SCA_IObject* gameobj, bool visible, bool occlusion, - bool recursive, - PyTypeObject* T=&Type - ); + bool recursive); virtual ~KX_VisibilityActuator( @@ -69,10 +67,6 @@ class KX_VisibilityActuator : public SCA_IActuator /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); - // Deprecated -----> KX_PYMETHOD_DOC_VARARGS(KX_VisibilityActuator,SetVisible); // <----- diff --git a/source/gameengine/VideoTexture/FilterBlueScreen.cpp b/source/gameengine/VideoTexture/FilterBlueScreen.cpp index 6b23105a278..6d26e5b6d35 100644 --- a/source/gameengine/VideoTexture/FilterBlueScreen.cpp +++ b/source/gameengine/VideoTexture/FilterBlueScreen.cpp @@ -81,17 +81,17 @@ static int setColor (PyFilter * self, PyObject * value, void * closure) { // check validity of parameter if (value == NULL || !PySequence_Check(value) || PySequence_Length(value) != 3 - || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 0)) - || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 1)) - || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 2))) + || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 0)) + || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 1)) + || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 2))) { PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 3 ints"); return -1; } // set color - getFilter(self)->setColor((unsigned char)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 0))), - (unsigned char)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 1))), - (unsigned char)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 2)))); + getFilter(self)->setColor((unsigned char)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 0))), + (unsigned char)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 1))), + (unsigned char)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 2)))); // success return 0; } @@ -108,15 +108,15 @@ static int setLimits (PyFilter * self, PyObject * value, void * closure) { // check validity of parameter if (value == NULL || !PySequence_Check(value) || PySequence_Length(value) != 2 - || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 0)) - || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 1))) + || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 0)) + || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 1))) { PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 2 ints"); return -1; } // set limits - getFilter(self)->setLimits((unsigned short)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 0))), - (unsigned short)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 1)))); + getFilter(self)->setLimits((unsigned short)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 0))), + (unsigned short)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 1)))); // success return 0; } diff --git a/source/gameengine/VideoTexture/FilterColor.cpp b/source/gameengine/VideoTexture/FilterColor.cpp index 5ff1f7f11ce..eb86f520e02 100644 --- a/source/gameengine/VideoTexture/FilterColor.cpp +++ b/source/gameengine/VideoTexture/FilterColor.cpp @@ -147,10 +147,10 @@ static int setMatrix (PyFilter * self, PyObject * value, void * closure) for (int c = 0; valid && c < 5; ++c) { // item must be int - valid = PyInt_Check(PySequence_Fast_GET_ITEM(row, c)); + valid = PyLong_Check(PySequence_Fast_GET_ITEM(row, c)); // if it is valid, save it in matrix if (valid) - mat[r][c] = short(PyInt_AsLong(PySequence_Fast_GET_ITEM(row, c))); + mat[r][c] = short(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(row, c))); } } // if parameter is not valid, report error @@ -286,10 +286,10 @@ static int setLevels (PyFilter * self, PyObject * value, void * closure) for (int c = 0; valid && c < 2; ++c) { // item must be int - valid = PyInt_Check(PySequence_Fast_GET_ITEM(row, c)); + valid = PyLong_Check(PySequence_Fast_GET_ITEM(row, c)); // if it is valid, save it in matrix if (valid) - lev[r][c] = (unsigned short)(PyInt_AsLong(PySequence_Fast_GET_ITEM(row, c))); + lev[r][c] = (unsigned short)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(row, c))); } } // if parameter is not valid, report error diff --git a/source/gameengine/VideoTexture/FilterNormal.cpp b/source/gameengine/VideoTexture/FilterNormal.cpp index 9a2b1e90d5a..002be6c3189 100644 --- a/source/gameengine/VideoTexture/FilterNormal.cpp +++ b/source/gameengine/VideoTexture/FilterNormal.cpp @@ -72,13 +72,13 @@ static PyObject * getColor (PyFilter * self, void * closure) static int setColor (PyFilter * self, PyObject * value, void * closure) { // check validity of parameter - if (value == NULL || !PyInt_Check(value)) + if (value == NULL || !PyLong_Check(value)) { PyErr_SetString(PyExc_TypeError, "filt.colorIdx = int: VideoTexture.FilterNormal, expected the value must be a int"); return -1; } // set color index - getFilter(self)->setColor((unsigned short)(PyInt_AsLong(value))); + getFilter(self)->setColor((unsigned short)(PyLong_AsSsize_t(value))); // success return 0; } diff --git a/source/gameengine/VideoTexture/ImageRender.cpp b/source/gameengine/VideoTexture/ImageRender.cpp index c4fb1fefd9c..d8be08e0eb5 100644 --- a/source/gameengine/VideoTexture/ImageRender.cpp +++ b/source/gameengine/VideoTexture/ImageRender.cpp @@ -331,19 +331,19 @@ static int setBackground (PyImage * self, PyObject * value, void * closure) { // check validity of parameter if (value == NULL || !PySequence_Check(value) || PySequence_Length(value) != 4 - || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 0)) - || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 1)) - || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 2)) - || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 3))) + || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 0)) + || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 1)) + || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 2)) + || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 3))) { PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 4 integer between 0 and 255"); return -1; } // set background color - getImageRender(self)->setBackground((unsigned char)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 0))), - (unsigned char)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 1))), - (unsigned char)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 2))), - (unsigned char)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 3)))); + getImageRender(self)->setBackground((unsigned char)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 0))), + (unsigned char)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 1))), + (unsigned char)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 2))), + (unsigned char)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 3)))); // success return 0; } diff --git a/source/gameengine/VideoTexture/ImageViewport.cpp b/source/gameengine/VideoTexture/ImageViewport.cpp index d2c23e758f6..55b14396280 100644 --- a/source/gameengine/VideoTexture/ImageViewport.cpp +++ b/source/gameengine/VideoTexture/ImageViewport.cpp @@ -218,16 +218,16 @@ static int ImageViewport_setPosition (PyImage * self, PyObject * value, void * c { // check validity of parameter if (value == NULL || !PySequence_Check(value) || PySequence_Length(value) != 2 - || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 0)) - || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 1))) + || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 0)) + || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 1))) { PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 2 ints"); return -1; } // set position GLint pos [] = { - GLint(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 0))), - GLint(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 1))) + GLint(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 0))), + GLint(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 1))) }; getImageViewport(self)->setPosition(pos); // success @@ -246,16 +246,16 @@ int ImageViewport_setCaptureSize (PyImage * self, PyObject * value, void * closu { // check validity of parameter if (value == NULL || !PySequence_Check(value) || PySequence_Length(value) != 2 - || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 0)) - || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 1))) + || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 0)) + || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 1))) { PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 2 ints"); return -1; } // set capture size short size [] = { - short(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 0))), - short(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 1))) + short(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 0))), + short(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 1))) }; getImageViewport(self)->setCaptureSize(size); // success diff --git a/source/gameengine/VideoTexture/VideoBase.cpp b/source/gameengine/VideoTexture/VideoBase.cpp index 5d449a158d8..5de7a9e80a9 100644 --- a/source/gameengine/VideoTexture/VideoBase.cpp +++ b/source/gameengine/VideoTexture/VideoBase.cpp @@ -167,13 +167,13 @@ PyObject * Video_getRepeat (PyImage * self, void * closure) int Video_setRepeat (PyImage * self, PyObject * value, void * closure) { // check validity of parameter - if (value == NULL || !PyInt_Check(value)) + if (value == NULL || !PyLong_Check(value)) { PyErr_SetString(PyExc_TypeError, "The value must be an int"); return -1; } // set repeat - getVideo(self)->setRepeat(int(PyInt_AsLong(value))); + getVideo(self)->setRepeat(int(PyLong_AsSsize_t(value))); // success return 0; } diff --git a/source/gameengine/VideoTexture/VideoFFmpeg.cpp b/source/gameengine/VideoTexture/VideoFFmpeg.cpp index 1a5481488c0..cf4ea88c1b5 100644 --- a/source/gameengine/VideoTexture/VideoFFmpeg.cpp +++ b/source/gameengine/VideoTexture/VideoFFmpeg.cpp @@ -1095,13 +1095,13 @@ PyObject * VideoFFmpeg_getPreseek (PyImage *self, void * closure) int VideoFFmpeg_setPreseek (PyImage * self, PyObject * value, void * closure) { // check validity of parameter - if (value == NULL || !PyInt_Check(value)) + if (value == NULL || !PyLong_Check(value)) { PyErr_SetString(PyExc_TypeError, "The value must be an integer"); return -1; } // set preseek - getFFmpeg(self)->setPreseek(PyInt_AsLong(value)); + getFFmpeg(self)->setPreseek(PyLong_AsSsize_t(value)); // success return 0; } diff --git a/source/gameengine/VideoTexture/blendVideoTex.cpp b/source/gameengine/VideoTexture/blendVideoTex.cpp index dad52a426b6..22171f69321 100644 --- a/source/gameengine/VideoTexture/blendVideoTex.cpp +++ b/source/gameengine/VideoTexture/blendVideoTex.cpp @@ -67,7 +67,7 @@ static PyObject * getMaterialID (PyObject *self, PyObject *args) // get last error description static PyObject * getLastError (PyObject *self, PyObject *args) { - return PyString_FromString(Exception::m_lastError.c_str()); + return PyUnicode_FromString(Exception::m_lastError.c_str()); } // set log file From 3373850e95dc07b4d7877df9180d1d82df87e31a Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 2 Jul 2009 03:50:20 +0000 Subject: [PATCH 076/114] NLA SoC: Bugfix for Auto-Keyframing version patching When auto-keying is enabled, the insertion mode is no-longer blank. The version patching code now takes this into account, but the conversion doesn't work for existing .b25.blend defaults files though. --- source/blender/blenloader/intern/readfile.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 0c1ba32c543..beebf58b6c0 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -9220,7 +9220,14 @@ static void do_versions(FileData *fd, Library *lib, Main *main) if(ts->normalsize == 0.0) { ts->normalsize= 0.1f; ts->selectmode= SCE_SELECT_VERTEX; + + /* autokeying - setting should be taken from the user-prefs + * but the userprefs version may not have correct flags set + * (i.e. will result in blank box when enabled) + */ ts->autokey_mode= U.autokey_mode; + if (ts->autokey_mode == 0) + ts->autokey_mode= 2; /* 'add/replace' but not on */ } } } From b47605d841d0c01b31199bce4499548ecf259bf1 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 2 Jul 2009 04:47:36 +0000 Subject: [PATCH 077/114] NLA SoC: Separating F-Modifier UI drawing into its own file * F-Modifier UI drawing/handling is now defined in a separate file so that it will be more suitable for inclusion into the NLA Editor's buttons. * Started removing F-Curve dependence from the modifier drawing code, which wasn't strictly necessary * Fixed F-Curve RNA wrapping to correctly use FPoints instead of the bulkier BPoints. Although nobody was likely to have encountered bugs here yet, this would almost certainly have contributed to some segfaults/data corruption along the track. --- .../blender/editors/animation/fmodifier_ui.c | 669 ++++++++++++++++++ source/blender/editors/include/ED_anim_api.h | 9 + .../editors/space_graph/graph_buttons.c | 573 +-------------- source/blender/makesrna/RNA_access.h | 1 + source/blender/makesrna/intern/rna_fcurve.c | 38 +- 5 files changed, 711 insertions(+), 579 deletions(-) create mode 100644 source/blender/editors/animation/fmodifier_ui.c diff --git a/source/blender/editors/animation/fmodifier_ui.c b/source/blender/editors/animation/fmodifier_ui.c new file mode 100644 index 00000000000..5968817a9a6 --- /dev/null +++ b/source/blender/editors/animation/fmodifier_ui.c @@ -0,0 +1,669 @@ +/** + * $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, Joshua Leung + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/* User-Interface Stuff for F-Modifiers: + * This file defines the (C-Coded) templates + editing callbacks needed + * by the interface stuff or F-Modifiers, as used by F-Curves in the Graph Editor, + * and NLA-Strips in the NLA Editor. + */ + +#include +#include +#include +#include + +#include "DNA_anim_types.h" +#include "DNA_action_types.h" +#include "DNA_object_types.h" +#include "DNA_space_types.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" +#include "DNA_userdef_types.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_arithb.h" +#include "BLI_blenlib.h" +#include "BLI_editVert.h" +#include "BLI_rand.h" + +#include "BKE_animsys.h" +#include "BKE_action.h" +#include "BKE_context.h" +#include "BKE_curve.h" +#include "BKE_customdata.h" +#include "BKE_depsgraph.h" +#include "BKE_fcurve.h" +#include "BKE_object.h" +#include "BKE_global.h" +#include "BKE_nla.h" +#include "BKE_scene.h" +#include "BKE_screen.h" +#include "BKE_utildefines.h" + +#include "BIF_gl.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "ED_anim_api.h" +#include "ED_keyframing.h" +#include "ED_screen.h" +#include "ED_types.h" +#include "ED_util.h" + +#include "UI_interface.h" +#include "UI_resources.h" +#include "UI_view2d.h" + +// XXX! -------------------------------- +/* temporary definition for limits of float number buttons (FLT_MAX tends to infinity with old system) */ +#define UI_FLT_MAX 10000.0f + +/* ********************************************** */ + +#define B_REDR 1 +#define B_FMODIFIER_REDRAW 20 + +/* macro for use here to draw background box and set height */ +// XXX for now, roundbox has it's callback func set to NULL to not intercept events +#define DRAW_BACKDROP(height) \ + { \ + uiDefBut(block, ROUNDBOX, B_REDR, "", -3, *yco-height, width+3, height-1, NULL, 5.0, 0.0, 12.0, (float)rb_col, ""); \ + } + +/* callback to verify modifier data */ +static void validate_fmodifier_cb (bContext *C, void *fcm_v, void *dummy) +{ + FModifier *fcm= (FModifier *)fcm_v; + FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); + + /* call the verify callback on the modifier if applicable */ + if (fmi && fmi->verify_data) + fmi->verify_data(fcm); +} + +/* callback to set the active modifier */ +static void activate_fmodifier_cb (bContext *C, void *fcu_v, void *fcm_v) +{ + FCurve *fcu= (FCurve *)fcu_v; + FModifier *fcm= (FModifier *)fcm_v; + + /* call API function to set the active modifier for active F-Curve */ + fcurve_set_active_modifier(fcu, fcm); +} + +/* callback to remove the given modifier */ +static void delete_fmodifier_cb (bContext *C, void *fcu_v, void *fcm_v) +{ + FCurve *fcu= (FCurve *)fcu_v; + FModifier *fcm= (FModifier *)fcm_v; + + /* remove the given F-Modifier from the F-Curve */ + fcurve_remove_modifier(fcu, fcm); +} + +/* --------------- */ + +/* draw settings for generator modifier */ +static void draw_modifier__generator(uiBlock *block, FModifier *fcm, int *yco, short *height, short width, short active, int rb_col) +{ + FMod_Generator *data= (FMod_Generator *)fcm->data; + char gen_mode[]="Generator Type%t|Expanded Polynomial%x0|Factorised Polynomial%x1"; + int cy= *yco - 30; + uiBut *but; + + /* set the height */ + (*height) = 90; + switch (data->mode) { + case FCM_GENERATOR_POLYNOMIAL: /* polynomial expression */ + (*height) += 20*(data->poly_order+1) + 20; + break; + case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* factorised polynomial */ + (*height) += 20 * data->poly_order + 15; + break; + } + + /* basic settings (backdrop + mode selector + some padding) */ + DRAW_BACKDROP((*height)); + uiBlockBeginAlign(block); + but= uiDefButI(block, MENU, B_FMODIFIER_REDRAW, gen_mode, 10,cy,width-30,19, &data->mode, 0, 0, 0, 0, "Selects type of generator algorithm."); + uiButSetFunc(but, validate_fmodifier_cb, fcm, NULL); + cy -= 20; + + uiDefButBitI(block, TOG, FCM_GENERATOR_ADDITIVE, B_FMODIFIER_REDRAW, "Additive", 10,cy,width-30,19, &data->flag, 0, 0, 0, 0, "Values generated by this modifier are applied on top of the existing values instead of overwriting them"); + cy -= 35; + uiBlockEndAlign(block); + + /* now add settings for individual modes */ + switch (data->mode) { + case FCM_GENERATOR_POLYNOMIAL: /* polynomial expression */ + { + float *cp = NULL; + char xval[32]; + unsigned int i; + + /* draw polynomial order selector */ + but= uiDefButI(block, NUM, B_FMODIFIER_REDRAW, "Poly Order: ", 10,cy,width-30,19, &data->poly_order, 1, 100, 0, 0, "'Order' of the Polynomial - for a polynomial with n terms, 'order' is n-1"); + uiButSetFunc(but, validate_fmodifier_cb, fcm, NULL); + cy -= 35; + + /* draw controls for each coefficient and a + sign at end of row */ + uiDefBut(block, LABEL, 1, "y = ", 0, cy, 50, 20, NULL, 0.0, 0.0, 0, 0, ""); + + cp= data->coefficients; + for (i=0; (i < data->arraysize) && (cp); i++, cp++) { + /* coefficient */ + uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 50, cy, 150, 20, cp, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "Coefficient for polynomial"); + + /* 'x' param (and '+' if necessary) */ + if (i == 0) + strcpy(xval, ""); + else if (i == 1) + strcpy(xval, "x"); + else + sprintf(xval, "x^%d", i); + uiDefBut(block, LABEL, 1, xval, 200, cy, 50, 20, NULL, 0.0, 0.0, 0, 0, "Power of x"); + + if ( (i != (data->arraysize - 1)) || ((i==0) && data->arraysize==2) ) + uiDefBut(block, LABEL, 1, "+", 250, cy, 30, 20, NULL, 0.0, 0.0, 0, 0, ""); + + cy -= 20; + } + } + break; + + case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* factorised polynomial expression */ + { + float *cp = NULL; + unsigned int i; + + /* draw polynomial order selector */ + but= uiDefButI(block, NUM, B_FMODIFIER_REDRAW, "Poly Order: ", 10,cy,width-30,19, &data->poly_order, 1, 100, 0, 0, "'Order' of the Polynomial - for a polynomial with n terms, 'order' is n-1"); + uiButSetFunc(but, validate_fmodifier_cb, fcm, NULL); + cy -= 35; + + /* draw controls for each pair of coefficients */ + uiDefBut(block, LABEL, 1, "y = ", 0, cy, 50, 20, NULL, 0.0, 0.0, 0, 0, ""); + + cp= data->coefficients; + for (i=0; (i < data->poly_order) && (cp); i++, cp+=2) { + /* opening bracket */ + uiDefBut(block, LABEL, 1, "(", 40, cy, 50, 20, NULL, 0.0, 0.0, 0, 0, ""); + + /* coefficients */ + uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 50, cy, 100, 20, cp, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "Coefficient of x"); + + uiDefBut(block, LABEL, 1, "x + ", 150, cy, 30, 20, NULL, 0.0, 0.0, 0, 0, ""); + + uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 180, cy, 100, 20, cp+1, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "Second coefficient"); + + /* closing bracket and '+' sign */ + if ( (i != (data->poly_order - 1)) || ((i==0) && data->poly_order==2) ) + uiDefBut(block, LABEL, 1, ") ?", 280, cy, 30, 20, NULL, 0.0, 0.0, 0, 0, ""); + else + uiDefBut(block, LABEL, 1, ")", 280, cy, 30, 20, NULL, 0.0, 0.0, 0, 0, ""); + + cy -= 20; + } + } + break; + } +} + +/* --------------- */ + +/* draw settings for noise modifier */ +static void draw_modifier__fn_generator(uiBlock *block, FModifier *fcm, int *yco, short *height, short width, short active, int rb_col) +{ + FMod_FunctionGenerator *data= (FMod_FunctionGenerator *)fcm->data; + int cy= (*yco - 30), cy1= (*yco - 50), cy2= (*yco - 70); + char fn_type[]="Built-In Function%t|Sin%x0|Cos%x1|Tan%x2|Square Root%x3|Natural Log%x4|Normalised Sin%x5"; + + /* set the height */ + (*height) = 80; + + /* basic settings (backdrop + some padding) */ + DRAW_BACKDROP((*height)); + + uiDefButI(block, MENU, B_FMODIFIER_REDRAW, fn_type, + 3, cy, 300, 20, &data->type, 0, 0, 0, 0, "Type of function used to generate values"); + + + uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Amplitude:", + 3, cy1, 150, 20, &data->amplitude, 0.000001, 10000.0, 0.01, 3, "Scale factor determining the maximum/minimum values."); + uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Value Offset:", + 3, cy2, 150, 20, &data->value_offset, 0.0, 10000.0, 0.01, 3, "Constant factor to offset values by."); + + uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Phase Multiplier:", + 155, cy1, 150, 20, &data->phase_multiplier, 0.0, 100000.0, 0.1, 3, "Scale factor determining the 'speed' of the function."); + uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Phase Offset:", + 155, cy2, 150, 20, &data->phase_offset, 0.0, 100000.0, 0.1, 3, "Constant factor to offset time by for function."); + +} + +/* --------------- */ + +/* draw settings for cycles modifier */ +static void draw_modifier__cycles(uiBlock *block, FModifier *fcm, int *yco, short *height, short width, short active, int rb_col) +{ + FMod_Cycles *data= (FMod_Cycles *)fcm->data; + char cyc_mode[]="Cycling Mode%t|No Cycles%x0|Repeat Motion%x1|Repeat with Offset%x2|Repeat Mirrored%x3"; + int cy= (*yco - 30), cy1= (*yco - 50), cy2= (*yco - 70); + + /* set the height */ + (*height) = 80; + + /* basic settings (backdrop + some padding) */ + DRAW_BACKDROP((*height)); + + /* 'before' range */ + uiDefBut(block, LABEL, 1, "Before:", 4, cy, 80, 20, NULL, 0.0, 0.0, 0, 0, "Settings for cycling before first keyframe"); + uiBlockBeginAlign(block); + uiDefButS(block, MENU, B_FMODIFIER_REDRAW, cyc_mode, 3,cy1,150,20, &data->before_mode, 0, 0, 0, 0, "Cycling mode to use before first keyframe"); + uiDefButS(block, NUM, B_FMODIFIER_REDRAW, "Max Cycles:", 3, cy2, 150, 20, &data->before_cycles, 0, 10000, 10, 3, "Maximum number of cycles to allow (0 = infinite)"); + uiBlockEndAlign(block); + + /* 'after' range */ + uiDefBut(block, LABEL, 1, "After:", 155, cy, 80, 20, NULL, 0.0, 0.0, 0, 0, "Settings for cycling after last keyframe"); + uiBlockBeginAlign(block); + uiDefButS(block, MENU, B_FMODIFIER_REDRAW, cyc_mode, 157,cy1,150,20, &data->after_mode, 0, 0, 0, 0, "Cycling mode to use after first keyframe"); + uiDefButS(block, NUM, B_FMODIFIER_REDRAW, "Max Cycles:", 157, cy2, 150, 20, &data->after_cycles, 0, 10000, 10, 3, "Maximum number of cycles to allow (0 = infinite)"); + uiBlockEndAlign(block); +} + +/* --------------- */ + +/* draw settings for noise modifier */ +static void draw_modifier__noise(uiBlock *block, FModifier *fcm, int *yco, short *height, short width, short active, int rb_col) +{ + FMod_Noise *data= (FMod_Noise *)fcm->data; + int cy= (*yco - 30), cy1= (*yco - 50), cy2= (*yco - 70); + char blend_mode[]="Modification %t|Replace %x0|Add %x1|Subtract %x2|Multiply %x3"; + + /* set the height */ + (*height) = 80; + + /* basic settings (backdrop + some padding) */ + DRAW_BACKDROP((*height)); + + uiDefButS(block, MENU, B_FMODIFIER_REDRAW, blend_mode, + 3, cy, 150, 20, &data->modification, 0, 0, 0, 0, "Method of combining the results of this modifier and other modifiers."); + + uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Size:", + 3, cy1, 150, 20, &data->size, 0.000001, 10000.0, 0.01, 3, ""); + uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Strength:", + 3, cy2, 150, 20, &data->strength, 0.0, 10000.0, 0.01, 3, ""); + + uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Phase:", + 155, cy1, 150, 20, &data->phase, 0.0, 100000.0, 0.1, 3, ""); + uiDefButS(block, NUM, B_FMODIFIER_REDRAW, "Depth:", + 155, cy2, 150, 20, &data->depth, 0, 128, 1, 3, ""); + +} + +/* --------------- */ + +#define BINARYSEARCH_FRAMEEQ_THRESH 0.0001 + +/* Binary search algorithm for finding where to insert Envelope Data Point. + * Returns the index to insert at (data already at that index will be offset if replace is 0) + */ +static int binarysearch_fcm_envelopedata_index (FCM_EnvelopeData array[], float frame, int arraylen, short *exists) +{ + int start=0, end=arraylen; + int loopbreaker= 0, maxloop= arraylen * 2; + + /* initialise exists-flag first */ + *exists= 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_fcm_envelopedata_index() encountered invalid array \n"); + return 0; + } + else { + /* check whether to add before/after/on */ + float framenum; + + /* 'First' Point (when only one point, this case is used) */ + framenum= array[0].time; + if (IS_EQT(frame, framenum, BINARYSEARCH_FRAMEEQ_THRESH)) { + *exists = 1; + return 0; + } + else if (frame < framenum) + return 0; + + /* 'Last' Point */ + framenum= array[(arraylen-1)].time; + if (IS_EQT(frame, framenum, BINARYSEARCH_FRAMEEQ_THRESH)) { + *exists= 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].time; + + /* check if exactly equal to midpoint */ + if (IS_EQT(frame, midfra, BINARYSEARCH_FRAMEEQ_THRESH)) { + *exists = 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_fcm_envelopedata_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; +} + +/* callback to add new envelope data point */ +// TODO: should we have a separate file for things like this? +static void fmod_envelope_addpoint_cb (bContext *C, void *fcm_dv, void *dummy) +{ + Scene *scene= CTX_data_scene(C); + FMod_Envelope *env= (FMod_Envelope *)fcm_dv; + FCM_EnvelopeData *fedn; + FCM_EnvelopeData fed; + + /* init template data */ + fed.min= -1.0f; + fed.max= 1.0f; + fed.time= (float)scene->r.cfra; // XXX make this int for ease of use? + fed.f1= fed.f2= 0; + + /* check that no data exists for the current frame... */ + if (env->data) { + short exists = -1; + int i= binarysearch_fcm_envelopedata_index(env->data, (float)(scene->r.cfra), env->totvert, &exists); + + /* binarysearch_...() will set exists by default to 0, so if it is non-zero, that means that the point exists already */ + if (exists) + return; + + /* add new */ + fedn= MEM_callocN((env->totvert+1)*sizeof(FCM_EnvelopeData), "FCM_EnvelopeData"); + + /* add the points that should occur before the point to be pasted */ + if (i > 0) + memcpy(fedn, env->data, i*sizeof(FCM_EnvelopeData)); + + /* add point to paste at index i */ + *(fedn + i)= fed; + + /* add the points that occur after the point to be pasted */ + if (i < env->totvert) + memcpy(fedn+i+1, env->data+i, (env->totvert-i)*sizeof(FCM_EnvelopeData)); + + /* replace (+ free) old with new */ + MEM_freeN(env->data); + env->data= fedn; + + env->totvert++; + } + else { + env->data= MEM_callocN(sizeof(FCM_EnvelopeData), "FCM_EnvelopeData"); + *(env->data)= fed; + + env->totvert= 1; + } +} + +/* callback to remove envelope data point */ +// TODO: should we have a separate file for things like this? +static void fmod_envelope_deletepoint_cb (bContext *C, void *fcm_dv, void *ind_v) +{ + FMod_Envelope *env= (FMod_Envelope *)fcm_dv; + FCM_EnvelopeData *fedn; + int index= GET_INT_FROM_POINTER(ind_v); + + /* check that no data exists for the current frame... */ + if (env->totvert > 1) { + /* allocate a new smaller array */ + fedn= MEM_callocN(sizeof(FCM_EnvelopeData)*(env->totvert-1), "FCM_EnvelopeData"); + + memcpy(fedn, &env->data, sizeof(FCM_EnvelopeData)*(index)); + memcpy(&fedn[index], &env->data[index+1], sizeof(FCM_EnvelopeData)*(env->totvert-index-1)); + + /* free old array, and set the new */ + MEM_freeN(env->data); + env->data= fedn; + env->totvert--; + } + else { + /* just free array, since the only vert was deleted */ + if (env->data) + MEM_freeN(env->data); + env->totvert= 0; + } +} + +/* draw settings for envelope modifier */ +static void draw_modifier__envelope(uiBlock *block, FModifier *fcm, int *yco, short *height, short width, short active, int rb_col) +{ + FMod_Envelope *env= (FMod_Envelope *)fcm->data; + FCM_EnvelopeData *fed; + uiBut *but; + int cy= (*yco - 28); + int i; + + /* set the height: + * - basic settings + variable height from envelope controls + */ + (*height) = 115 + (35 * env->totvert); + + /* basic settings (backdrop + general settings + some padding) */ + DRAW_BACKDROP((*height)); + + /* General Settings */ + uiDefBut(block, LABEL, 1, "Envelope:", 10, cy, 100, 20, NULL, 0.0, 0.0, 0, 0, "Settings for cycling before first keyframe"); + cy -= 20; + + uiBlockBeginAlign(block); + uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Reference Val:", 10, cy, 300, 20, &env->midval, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, ""); + cy -= 20; + + uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Min:", 10, cy, 150, 20, &env->min, -UI_FLT_MAX, env->max, 10, 3, "Minimum value (relative to Reference Value) that is used as the 'normal' minimum value"); + uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Max:", 160, cy, 150, 20, &env->max, env->min, UI_FLT_MAX, 10, 3, "Maximum value (relative to Reference Value) that is used as the 'normal' maximum value"); + cy -= 35; + uiBlockEndAlign(block); + + + /* Points header */ + uiDefBut(block, LABEL, 1, "Control Points:", 10, cy, 150, 20, NULL, 0.0, 0.0, 0, 0, ""); + + but= uiDefBut(block, BUT, B_FMODIFIER_REDRAW, "Add Point", 160,cy,150,19, NULL, 0, 0, 0, 0, "Adds a new control-point to the envelope on the current frame"); + uiButSetFunc(but, fmod_envelope_addpoint_cb, env, NULL); + cy -= 35; + + /* Points List */ + for (i=0, fed=env->data; i < env->totvert; i++, fed++) { + uiBlockBeginAlign(block); + but=uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Fra:", 2, cy, 90, 20, &fed->time, -UI_FLT_MAX, UI_FLT_MAX, 10, 1, "Frame that envelope point occurs"); + uiButSetFunc(but, validate_fmodifier_cb, fcm, NULL); + + uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Min:", 92, cy, 100, 20, &fed->min, -UI_FLT_MAX, UI_FLT_MAX, 10, 2, "Minimum bound of envelope at this point"); + uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Max:", 192, cy, 100, 20, &fed->max, -UI_FLT_MAX, UI_FLT_MAX, 10, 2, "Maximum bound of envelope at this point"); + + but= uiDefIconBut(block, BUT, B_FMODIFIER_REDRAW, ICON_X, 292, cy, 18, 20, NULL, 0.0, 0.0, 0.0, 0.0, "Delete envelope control point"); + uiButSetFunc(but, fmod_envelope_deletepoint_cb, env, SET_INT_IN_POINTER(i)); + uiBlockBeginAlign(block); + cy -= 25; + } +} + +/* --------------- */ + +/* draw settings for limits modifier */ +static void draw_modifier__limits(uiBlock *block, FModifier *fcm, int *yco, short *height, short width, short active, int rb_col) +{ + FMod_Limits *data= (FMod_Limits *)fcm->data; + const int togButWidth = 50; + const int textButWidth = ((width/2)-togButWidth); + + /* set the height */ + (*height) = 60; + + /* basic settings (backdrop + some padding) */ + DRAW_BACKDROP((*height)); + + /* Draw Pairs of LimitToggle+LimitValue */ + uiBlockBeginAlign(block); + uiDefButBitI(block, TOGBUT, FCM_LIMIT_XMIN, B_FMODIFIER_REDRAW, "xMin", 5, *yco-30, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum x value"); + uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 5+togButWidth, *yco-30, (textButWidth-5), 18, &data->rect.xmin, -UI_FLT_MAX, UI_FLT_MAX, 0.1,0.5,"Lowest x value to allow"); + uiBlockEndAlign(block); + + uiBlockBeginAlign(block); + uiDefButBitI(block, TOGBUT, FCM_LIMIT_XMAX, B_FMODIFIER_REDRAW, "XMax", 5+(width-(textButWidth-5)-togButWidth), *yco-30, 50, 18, &data->flag, 0, 24, 0, 0, "Use maximum x value"); + uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 5+(width-textButWidth-5), *yco-30, (textButWidth-5), 18, &data->rect.xmax, -UI_FLT_MAX, UI_FLT_MAX, 0.1,0.5,"Highest x value to allow"); + uiBlockEndAlign(block); + + uiBlockBeginAlign(block); + uiDefButBitI(block, TOGBUT, FCM_LIMIT_YMIN, B_FMODIFIER_REDRAW, "yMin", 5, *yco-52, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum y value"); + uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 5+togButWidth, *yco-52, (textButWidth-5), 18, &data->rect.ymin, -UI_FLT_MAX, UI_FLT_MAX, 0.1,0.5,"Lowest y value to allow"); + uiBlockEndAlign(block); + + uiBlockBeginAlign(block); + uiDefButBitI(block, TOGBUT, FCM_LIMIT_YMAX, B_FMODIFIER_REDRAW, "YMax", 5+(width-(textButWidth-5)-togButWidth), *yco-52, 50, 18, &data->flag, 0, 24, 0, 0, "Use maximum y value"); + uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 5+(width-textButWidth-5), *yco-52, (textButWidth-5), 18, &data->rect.ymax, -UI_FLT_MAX, UI_FLT_MAX, 0.1,0.5,"Highest y value to allow"); + uiBlockEndAlign(block); +} + +/* --------------- */ + +// FIXME: remove dependency for F-Curve +void ANIM_uiTemplate_fmodifier_draw (uiBlock *block, FCurve *fcu, FModifier *fcm, int *yco) +{ + FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); + uiBut *but; + short active= (fcm->flag & FMODIFIER_FLAG_ACTIVE); + short width= 314; + short height = 0; + int rb_col; + + /* draw header */ + { + uiBlockSetEmboss(block, UI_EMBOSSN); + + /* rounded header */ + rb_col= (active)?-20:20; + but= uiDefBut(block, ROUNDBOX, B_REDR, "", 0, *yco-2, width, 24, NULL, 5.0, 0.0, 15.0, (float)(rb_col-20), ""); + + /* expand */ + uiDefIconButBitS(block, ICONTOG, FMODIFIER_FLAG_EXPANDED, B_REDR, ICON_TRIA_RIGHT, 5, *yco-1, 20, 20, &fcm->flag, 0.0, 0.0, 0, 0, "Modifier is expanded."); + + /* checkbox for 'active' status (for now) */ + but= uiDefIconButBitS(block, ICONTOG, FMODIFIER_FLAG_ACTIVE, B_REDR, ICON_RADIOBUT_OFF, 25, *yco-1, 20, 20, &fcm->flag, 0.0, 0.0, 0, 0, "Modifier is active one."); + uiButSetFunc(but, activate_fmodifier_cb, fcu, fcm); + + /* name */ + if (fmi) + uiDefBut(block, LABEL, 1, fmi->name, 10+40, *yco, 150, 20, NULL, 0.0, 0.0, 0, 0, "F-Curve Modifier Type. Click to make modifier active one."); + else + uiDefBut(block, LABEL, 1, "", 10+40, *yco, 150, 20, NULL, 0.0, 0.0, 0, 0, "F-Curve Modifier Type. Click to make modifier active one."); + + /* 'mute' button */ + uiDefIconButBitS(block, ICONTOG, FMODIFIER_FLAG_MUTED, B_REDR, ICON_MUTE_IPO_OFF, 10+(width-60), *yco-1, 20, 20, &fcm->flag, 0.0, 0.0, 0, 0, "Modifier is temporarily muted (not evaluated)."); + + /* delete button */ + but= uiDefIconBut(block, BUT, B_REDR, ICON_X, 10+(width-30), *yco, 19, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Delete F-Curve Modifier."); + uiButSetFunc(but, delete_fmodifier_cb, fcu, fcm); + + uiBlockSetEmboss(block, UI_EMBOSS); + } + + /* when modifier is expanded, draw settings */ + if (fcm->flag & FMODIFIER_FLAG_EXPANDED) { + /* draw settings for individual modifiers */ + switch (fcm->type) { + case FMODIFIER_TYPE_GENERATOR: /* Generator */ + draw_modifier__generator(block, fcm, yco, &height, width, active, rb_col); + break; + + case FMODIFIER_TYPE_FN_GENERATOR: /* Built-In Function Generator */ + draw_modifier__fn_generator(block, fcm, yco, &height, width, active, rb_col); + break; + + case FMODIFIER_TYPE_CYCLES: /* Cycles */ + draw_modifier__cycles(block, fcm, yco, &height, width, active, rb_col); + break; + + case FMODIFIER_TYPE_ENVELOPE: /* Envelope */ + draw_modifier__envelope(block, fcm, yco, &height, width, active, rb_col); + break; + + case FMODIFIER_TYPE_LIMITS: /* Limits */ + draw_modifier__limits(block, fcm, yco, &height, width, active, rb_col); + break; + + case FMODIFIER_TYPE_NOISE: /* Noise */ + draw_modifier__noise(block, fcm, yco, &height, width, active, rb_col); + break; + + default: /* unknown type */ + height= 96; + //DRAW_BACKDROP(height); // XXX buggy... + break; + } + } + + /* adjust height for new to start */ + (*yco) -= (height + 27); +} + +/* ********************************************** */ + + \ No newline at end of file diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index 4bfcbde8f1e..4d75a73a327 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -293,6 +293,15 @@ 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); +/* ************************************************* */ +/* F-MODIFIER TOOLS */ + +struct uiBlock; + +/* draw a given F-Modifier for some layout/UI-Block */ +// XXX not quite complete yet +void ANIM_uiTemplate_fmodifier_draw(struct uiBlock *block, struct FCurve *fcu, struct FModifier *fcm, int *yco); + /* ************************************************* */ /* ASSORTED TOOLS */ diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c index e68ee53521d..9d4a1a8b3cb 100644 --- a/source/blender/editors/space_graph/graph_buttons.c +++ b/source/blender/editors/space_graph/graph_buttons.c @@ -347,6 +347,7 @@ static void graph_panel_drivers(const bContext *C, Panel *pa) } /* ******************* f-modifiers ******************************** */ +/* all the drawing code is in editors/animation/fmodifier_ui.c */ #define B_FMODIFIER_REDRAW 20 @@ -360,576 +361,6 @@ static void do_graph_region_modifier_buttons(bContext *C, void *arg, int event) } } -/* macro for use here to draw background box and set height */ -// XXX for now, roundbox has it's callback func set to NULL to not intercept events -#define DRAW_BACKDROP(height) \ - { \ - uiDefBut(block, ROUNDBOX, B_REDR, "", -3, *yco-height, width+3, height-1, NULL, 5.0, 0.0, 12.0, (float)rb_col, ""); \ - } - -/* callback to verify modifier data */ -static void validate_fmodifier_cb (bContext *C, void *fcu_v, void *fcm_v) -{ - FModifier *fcm= (FModifier *)fcm_v; - FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); - - /* call the verify callback on the modifier if applicable */ - if (fmi && fmi->verify_data) - fmi->verify_data(fcm); -} - -/* callback to set the active modifier */ -static void activate_fmodifier_cb (bContext *C, void *fcu_v, void *fcm_v) -{ - FCurve *fcu= (FCurve *)fcu_v; - FModifier *fcm= (FModifier *)fcm_v; - - /* call API function to set the active modifier for active F-Curve */ - fcurve_set_active_modifier(fcu, fcm); -} - -/* callback to remove the given modifier */ -static void delete_fmodifier_cb (bContext *C, void *fcu_v, void *fcm_v) -{ - FCurve *fcu= (FCurve *)fcu_v; - FModifier *fcm= (FModifier *)fcm_v; - - /* remove the given F-Modifier from the F-Curve */ - fcurve_remove_modifier(fcu, fcm); -} - -/* --------------- */ - -/* draw settings for generator modifier */ -static void draw_modifier__generator(uiBlock *block, FCurve *fcu, FModifier *fcm, int *yco, short *height, short width, short active, int rb_col) -{ - FMod_Generator *data= (FMod_Generator *)fcm->data; - char gen_mode[]="Generator Type%t|Expanded Polynomial%x0|Factorised Polynomial%x1"; - int cy= *yco - 30; - uiBut *but; - - /* set the height */ - (*height) = 90; - switch (data->mode) { - case FCM_GENERATOR_POLYNOMIAL: /* polynomial expression */ - (*height) += 20*(data->poly_order+1) + 20; - break; - case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* factorised polynomial */ - (*height) += 20 * data->poly_order + 15; - break; - } - - /* basic settings (backdrop + mode selector + some padding) */ - DRAW_BACKDROP((*height)); - uiBlockBeginAlign(block); - but= uiDefButI(block, MENU, B_FMODIFIER_REDRAW, gen_mode, 10,cy,width-30,19, &data->mode, 0, 0, 0, 0, "Selects type of generator algorithm."); - uiButSetFunc(but, validate_fmodifier_cb, fcu, fcm); - cy -= 20; - - uiDefButBitI(block, TOG, FCM_GENERATOR_ADDITIVE, B_FMODIFIER_REDRAW, "Additive", 10,cy,width-30,19, &data->flag, 0, 0, 0, 0, "Values generated by this modifier are applied on top of the existing values instead of overwriting them"); - cy -= 35; - uiBlockEndAlign(block); - - /* now add settings for individual modes */ - switch (data->mode) { - case FCM_GENERATOR_POLYNOMIAL: /* polynomial expression */ - { - float *cp = NULL; - char xval[32]; - unsigned int i; - - /* draw polynomial order selector */ - but= uiDefButI(block, NUM, B_FMODIFIER_REDRAW, "Poly Order: ", 10,cy,width-30,19, &data->poly_order, 1, 100, 0, 0, "'Order' of the Polynomial - for a polynomial with n terms, 'order' is n-1"); - uiButSetFunc(but, validate_fmodifier_cb, fcu, fcm); - cy -= 35; - - /* draw controls for each coefficient and a + sign at end of row */ - uiDefBut(block, LABEL, 1, "y = ", 0, cy, 50, 20, NULL, 0.0, 0.0, 0, 0, ""); - - cp= data->coefficients; - for (i=0; (i < data->arraysize) && (cp); i++, cp++) { - /* coefficient */ - uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 50, cy, 150, 20, cp, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "Coefficient for polynomial"); - - /* 'x' param (and '+' if necessary) */ - if (i == 0) - strcpy(xval, ""); - else if (i == 1) - strcpy(xval, "x"); - else - sprintf(xval, "x^%d", i); - uiDefBut(block, LABEL, 1, xval, 200, cy, 50, 20, NULL, 0.0, 0.0, 0, 0, "Power of x"); - - if ( (i != (data->arraysize - 1)) || ((i==0) && data->arraysize==2) ) - uiDefBut(block, LABEL, 1, "+", 250, cy, 30, 20, NULL, 0.0, 0.0, 0, 0, ""); - - cy -= 20; - } - } - break; - - case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* factorised polynomial expression */ - { - float *cp = NULL; - unsigned int i; - - /* draw polynomial order selector */ - but= uiDefButI(block, NUM, B_FMODIFIER_REDRAW, "Poly Order: ", 10,cy,width-30,19, &data->poly_order, 1, 100, 0, 0, "'Order' of the Polynomial - for a polynomial with n terms, 'order' is n-1"); - uiButSetFunc(but, validate_fmodifier_cb, fcu, fcm); - cy -= 35; - - /* draw controls for each pair of coefficients */ - uiDefBut(block, LABEL, 1, "y = ", 0, cy, 50, 20, NULL, 0.0, 0.0, 0, 0, ""); - - cp= data->coefficients; - for (i=0; (i < data->poly_order) && (cp); i++, cp+=2) { - /* opening bracket */ - uiDefBut(block, LABEL, 1, "(", 40, cy, 50, 20, NULL, 0.0, 0.0, 0, 0, ""); - - /* coefficients */ - uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 50, cy, 100, 20, cp, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "Coefficient of x"); - - uiDefBut(block, LABEL, 1, "x + ", 150, cy, 30, 20, NULL, 0.0, 0.0, 0, 0, ""); - - uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 180, cy, 100, 20, cp+1, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "Second coefficient"); - - /* closing bracket and '+' sign */ - if ( (i != (data->poly_order - 1)) || ((i==0) && data->poly_order==2) ) - uiDefBut(block, LABEL, 1, ") â—Š", 280, cy, 30, 20, NULL, 0.0, 0.0, 0, 0, ""); - else - uiDefBut(block, LABEL, 1, ")", 280, cy, 30, 20, NULL, 0.0, 0.0, 0, 0, ""); - - cy -= 20; - } - } - break; - } -} - -/* --------------- */ - -/* draw settings for noise modifier */ -static void draw_modifier__fn_generator(uiBlock *block, FCurve *fcu, FModifier *fcm, int *yco, short *height, short width, short active, int rb_col) -{ - FMod_FunctionGenerator *data= (FMod_FunctionGenerator *)fcm->data; - int cy= (*yco - 30), cy1= (*yco - 50), cy2= (*yco - 70); - char fn_type[]="Built-In Function%t|Sin%x0|Cos%x1|Tan%x2|Square Root%x3|Natural Log%x4|Normalised Sin%x5"; - - /* set the height */ - (*height) = 80; - - /* basic settings (backdrop + some padding) */ - DRAW_BACKDROP((*height)); - - uiDefButI(block, MENU, B_FMODIFIER_REDRAW, fn_type, - 3, cy, 300, 20, &data->type, 0, 0, 0, 0, "Type of function used to generate values"); - - - uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Amplitude:", - 3, cy1, 150, 20, &data->amplitude, 0.000001, 10000.0, 0.01, 3, "Scale factor determining the maximum/minimum values."); - uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Value Offset:", - 3, cy2, 150, 20, &data->value_offset, 0.0, 10000.0, 0.01, 3, "Constant factor to offset values by."); - - uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Phase Multiplier:", - 155, cy1, 150, 20, &data->phase_multiplier, 0.0, 100000.0, 0.1, 3, "Scale factor determining the 'speed' of the function."); - uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Phase Offset:", - 155, cy2, 150, 20, &data->phase_offset, 0.0, 100000.0, 0.1, 3, "Constant factor to offset time by for function."); - -} - -/* --------------- */ - -/* draw settings for cycles modifier */ -static void draw_modifier__cycles(uiBlock *block, FCurve *fcu, FModifier *fcm, int *yco, short *height, short width, short active, int rb_col) -{ - FMod_Cycles *data= (FMod_Cycles *)fcm->data; - char cyc_mode[]="Cycling Mode%t|No Cycles%x0|Repeat Motion%x1|Repeat with Offset%x2|Repeat Mirrored%x3"; - int cy= (*yco - 30), cy1= (*yco - 50), cy2= (*yco - 70); - - /* set the height */ - (*height) = 80; - - /* basic settings (backdrop + some padding) */ - DRAW_BACKDROP((*height)); - - /* 'before' range */ - uiDefBut(block, LABEL, 1, "Before:", 4, cy, 80, 20, NULL, 0.0, 0.0, 0, 0, "Settings for cycling before first keyframe"); - uiBlockBeginAlign(block); - uiDefButS(block, MENU, B_FMODIFIER_REDRAW, cyc_mode, 3,cy1,150,20, &data->before_mode, 0, 0, 0, 0, "Cycling mode to use before first keyframe"); - uiDefButS(block, NUM, B_FMODIFIER_REDRAW, "Max Cycles:", 3, cy2, 150, 20, &data->before_cycles, 0, 10000, 10, 3, "Maximum number of cycles to allow (0 = infinite)"); - uiBlockEndAlign(block); - - /* 'after' range */ - uiDefBut(block, LABEL, 1, "After:", 155, cy, 80, 20, NULL, 0.0, 0.0, 0, 0, "Settings for cycling after last keyframe"); - uiBlockBeginAlign(block); - uiDefButS(block, MENU, B_FMODIFIER_REDRAW, cyc_mode, 157,cy1,150,20, &data->after_mode, 0, 0, 0, 0, "Cycling mode to use after first keyframe"); - uiDefButS(block, NUM, B_FMODIFIER_REDRAW, "Max Cycles:", 157, cy2, 150, 20, &data->after_cycles, 0, 10000, 10, 3, "Maximum number of cycles to allow (0 = infinite)"); - uiBlockEndAlign(block); -} - -/* --------------- */ - -/* draw settings for noise modifier */ -static void draw_modifier__noise(uiBlock *block, FCurve *fcu, FModifier *fcm, int *yco, short *height, short width, short active, int rb_col) -{ - FMod_Noise *data= (FMod_Noise *)fcm->data; - int cy= (*yco - 30), cy1= (*yco - 50), cy2= (*yco - 70); - char blend_mode[]="Modification %t|Replace %x0|Add %x1|Subtract %x2|Multiply %x3"; - - /* set the height */ - (*height) = 80; - - /* basic settings (backdrop + some padding) */ - DRAW_BACKDROP((*height)); - - uiDefButS(block, MENU, B_FMODIFIER_REDRAW, blend_mode, - 3, cy, 150, 20, &data->modification, 0, 0, 0, 0, "Method of combining the results of this modifier and other modifiers."); - - uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Size:", - 3, cy1, 150, 20, &data->size, 0.000001, 10000.0, 0.01, 3, ""); - uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Strength:", - 3, cy2, 150, 20, &data->strength, 0.0, 10000.0, 0.01, 3, ""); - - uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Phase:", - 155, cy1, 150, 20, &data->phase, 0.0, 100000.0, 0.1, 3, ""); - uiDefButS(block, NUM, B_FMODIFIER_REDRAW, "Depth:", - 155, cy2, 150, 20, &data->depth, 0, 128, 1, 3, ""); - -} - -/* --------------- */ - -#define BINARYSEARCH_FRAMEEQ_THRESH 0.0001 - -/* Binary search algorithm for finding where to insert Envelope Data Point. - * Returns the index to insert at (data already at that index will be offset if replace is 0) - */ -static int binarysearch_fcm_envelopedata_index (FCM_EnvelopeData array[], float frame, int arraylen, short *exists) -{ - int start=0, end=arraylen; - int loopbreaker= 0, maxloop= arraylen * 2; - - /* initialise exists-flag first */ - *exists= 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_fcm_envelopedata_index() encountered invalid array \n"); - return 0; - } - else { - /* check whether to add before/after/on */ - float framenum; - - /* 'First' Point (when only one point, this case is used) */ - framenum= array[0].time; - if (IS_EQT(frame, framenum, BINARYSEARCH_FRAMEEQ_THRESH)) { - *exists = 1; - return 0; - } - else if (frame < framenum) - return 0; - - /* 'Last' Point */ - framenum= array[(arraylen-1)].time; - if (IS_EQT(frame, framenum, BINARYSEARCH_FRAMEEQ_THRESH)) { - *exists= 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].time; - - /* check if exactly equal to midpoint */ - if (IS_EQT(frame, midfra, BINARYSEARCH_FRAMEEQ_THRESH)) { - *exists = 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_fcm_envelopedata_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; -} - -/* callback to add new envelope data point */ -// TODO: should we have a separate file for things like this? -static void fmod_envelope_addpoint_cb (bContext *C, void *fcm_dv, void *dummy) -{ - Scene *scene= CTX_data_scene(C); - FMod_Envelope *env= (FMod_Envelope *)fcm_dv; - FCM_EnvelopeData *fedn; - FCM_EnvelopeData fed; - - /* init template data */ - fed.min= -1.0f; - fed.max= 1.0f; - fed.time= (float)scene->r.cfra; // XXX make this int for ease of use? - fed.f1= fed.f2= 0; - - /* check that no data exists for the current frame... */ - if (env->data) { - short exists = -1; - int i= binarysearch_fcm_envelopedata_index(env->data, (float)(scene->r.cfra), env->totvert, &exists); - - /* binarysearch_...() will set exists by default to 0, so if it is non-zero, that means that the point exists already */ - if (exists) - return; - - /* add new */ - fedn= MEM_callocN((env->totvert+1)*sizeof(FCM_EnvelopeData), "FCM_EnvelopeData"); - - /* add the points that should occur before the point to be pasted */ - if (i > 0) - memcpy(fedn, env->data, i*sizeof(FCM_EnvelopeData)); - - /* add point to paste at index i */ - *(fedn + i)= fed; - - /* add the points that occur after the point to be pasted */ - if (i < env->totvert) - memcpy(fedn+i+1, env->data+i, (env->totvert-i)*sizeof(FCM_EnvelopeData)); - - /* replace (+ free) old with new */ - MEM_freeN(env->data); - env->data= fedn; - - env->totvert++; - } - else { - env->data= MEM_callocN(sizeof(FCM_EnvelopeData), "FCM_EnvelopeData"); - *(env->data)= fed; - - env->totvert= 1; - } -} - -/* callback to remove envelope data point */ -// TODO: should we have a separate file for things like this? -static void fmod_envelope_deletepoint_cb (bContext *C, void *fcm_dv, void *ind_v) -{ - FMod_Envelope *env= (FMod_Envelope *)fcm_dv; - FCM_EnvelopeData *fedn; - int index= GET_INT_FROM_POINTER(ind_v); - - /* check that no data exists for the current frame... */ - if (env->totvert > 1) { - /* allocate a new smaller array */ - fedn= MEM_callocN(sizeof(FCM_EnvelopeData)*(env->totvert-1), "FCM_EnvelopeData"); - - memcpy(fedn, &env->data, sizeof(FCM_EnvelopeData)*(index)); - memcpy(&fedn[index], &env->data[index+1], sizeof(FCM_EnvelopeData)*(env->totvert-index-1)); - - /* free old array, and set the new */ - MEM_freeN(env->data); - env->data= fedn; - env->totvert--; - } - else { - /* just free array, since the only vert was deleted */ - if (env->data) - MEM_freeN(env->data); - env->totvert= 0; - } -} - -/* draw settings for envelope modifier */ -static void draw_modifier__envelope(uiBlock *block, FCurve *fcu, FModifier *fcm, int *yco, short *height, short width, short active, int rb_col) -{ - FMod_Envelope *env= (FMod_Envelope *)fcm->data; - FCM_EnvelopeData *fed; - uiBut *but; - int cy= (*yco - 28); - int i; - - /* set the height: - * - basic settings + variable height from envelope controls - */ - (*height) = 115 + (35 * env->totvert); - - /* basic settings (backdrop + general settings + some padding) */ - DRAW_BACKDROP((*height)); - - /* General Settings */ - uiDefBut(block, LABEL, 1, "Envelope:", 10, cy, 100, 20, NULL, 0.0, 0.0, 0, 0, "Settings for cycling before first keyframe"); - cy -= 20; - - uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Reference Val:", 10, cy, 300, 20, &env->midval, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, ""); - cy -= 20; - - uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Min:", 10, cy, 150, 20, &env->min, -UI_FLT_MAX, env->max, 10, 3, "Minimum value (relative to Reference Value) that is used as the 'normal' minimum value"); - uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Max:", 160, cy, 150, 20, &env->max, env->min, UI_FLT_MAX, 10, 3, "Maximum value (relative to Reference Value) that is used as the 'normal' maximum value"); - cy -= 35; - uiBlockEndAlign(block); - - - /* Points header */ - uiDefBut(block, LABEL, 1, "Control Points:", 10, cy, 150, 20, NULL, 0.0, 0.0, 0, 0, ""); - - but= uiDefBut(block, BUT, B_FMODIFIER_REDRAW, "Add Point", 160,cy,150,19, NULL, 0, 0, 0, 0, "Adds a new control-point to the envelope on the current frame"); - uiButSetFunc(but, fmod_envelope_addpoint_cb, env, NULL); - cy -= 35; - - /* Points List */ - for (i=0, fed=env->data; i < env->totvert; i++, fed++) { - uiBlockBeginAlign(block); - but=uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Fra:", 2, cy, 90, 20, &fed->time, -UI_FLT_MAX, UI_FLT_MAX, 10, 1, "Frame that envelope point occurs"); - uiButSetFunc(but, validate_fmodifier_cb, fcu, fcm); - - uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Min:", 92, cy, 100, 20, &fed->min, -UI_FLT_MAX, UI_FLT_MAX, 10, 2, "Minimum bound of envelope at this point"); - uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Max:", 192, cy, 100, 20, &fed->max, -UI_FLT_MAX, UI_FLT_MAX, 10, 2, "Maximum bound of envelope at this point"); - - but= uiDefIconBut(block, BUT, B_FMODIFIER_REDRAW, ICON_X, 292, cy, 18, 20, NULL, 0.0, 0.0, 0.0, 0.0, "Delete envelope control point"); - uiButSetFunc(but, fmod_envelope_deletepoint_cb, env, SET_INT_IN_POINTER(i)); - uiBlockBeginAlign(block); - cy -= 25; - } -} - -/* --------------- */ - -/* draw settings for limits modifier */ -static void draw_modifier__limits(uiBlock *block, FCurve *fcu, FModifier *fcm, int *yco, short *height, short width, short active, int rb_col) -{ - FMod_Limits *data= (FMod_Limits *)fcm->data; - const int togButWidth = 50; - const int textButWidth = ((width/2)-togButWidth); - - /* set the height */ - (*height) = 60; - - /* basic settings (backdrop + some padding) */ - DRAW_BACKDROP((*height)); - - /* Draw Pairs of LimitToggle+LimitValue */ - uiBlockBeginAlign(block); - uiDefButBitI(block, TOGBUT, FCM_LIMIT_XMIN, B_FMODIFIER_REDRAW, "xMin", 5, *yco-30, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum x value"); - uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 5+togButWidth, *yco-30, (textButWidth-5), 18, &data->rect.xmin, -UI_FLT_MAX, UI_FLT_MAX, 0.1,0.5,"Lowest x value to allow"); - uiBlockEndAlign(block); - - uiBlockBeginAlign(block); - uiDefButBitI(block, TOGBUT, FCM_LIMIT_XMAX, B_FMODIFIER_REDRAW, "XMax", 5+(width-(textButWidth-5)-togButWidth), *yco-30, 50, 18, &data->flag, 0, 24, 0, 0, "Use maximum x value"); - uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 5+(width-textButWidth-5), *yco-30, (textButWidth-5), 18, &data->rect.xmax, -UI_FLT_MAX, UI_FLT_MAX, 0.1,0.5,"Highest x value to allow"); - uiBlockEndAlign(block); - - uiBlockBeginAlign(block); - uiDefButBitI(block, TOGBUT, FCM_LIMIT_YMIN, B_FMODIFIER_REDRAW, "yMin", 5, *yco-52, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum y value"); - uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 5+togButWidth, *yco-52, (textButWidth-5), 18, &data->rect.ymin, -UI_FLT_MAX, UI_FLT_MAX, 0.1,0.5,"Lowest y value to allow"); - uiBlockEndAlign(block); - - uiBlockBeginAlign(block); - uiDefButBitI(block, TOGBUT, FCM_LIMIT_YMAX, B_FMODIFIER_REDRAW, "YMax", 5+(width-(textButWidth-5)-togButWidth), *yco-52, 50, 18, &data->flag, 0, 24, 0, 0, "Use maximum y value"); - uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 5+(width-textButWidth-5), *yco-52, (textButWidth-5), 18, &data->rect.ymax, -UI_FLT_MAX, UI_FLT_MAX, 0.1,0.5,"Highest y value to allow"); - uiBlockEndAlign(block); -} - -/* --------------- */ - -static void graph_panel_modifier_draw(uiBlock *block, FCurve *fcu, FModifier *fcm, int *yco) -{ - FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); - uiBut *but; - short active= (fcm->flag & FMODIFIER_FLAG_ACTIVE); - short width= 314; - short height = 0; - int rb_col; - - /* draw header */ - { - uiBlockSetEmboss(block, UI_EMBOSSN); - - /* rounded header */ - rb_col= (active)?-20:20; - but= uiDefBut(block, ROUNDBOX, B_REDR, "", 0, *yco-2, width, 24, NULL, 5.0, 0.0, 15.0, (float)(rb_col-20), ""); - - /* expand */ - uiDefIconButBitS(block, ICONTOG, FMODIFIER_FLAG_EXPANDED, B_REDR, ICON_TRIA_RIGHT, 5, *yco-1, 20, 20, &fcm->flag, 0.0, 0.0, 0, 0, "Modifier is expanded."); - - /* checkbox for 'active' status (for now) */ - but= uiDefIconButBitS(block, ICONTOG, FMODIFIER_FLAG_ACTIVE, B_REDR, ICON_RADIOBUT_OFF, 25, *yco-1, 20, 20, &fcm->flag, 0.0, 0.0, 0, 0, "Modifier is active one."); - uiButSetFunc(but, activate_fmodifier_cb, fcu, fcm); - - /* name */ - if (fmi) - uiDefBut(block, LABEL, 1, fmi->name, 10+40, *yco, 150, 20, NULL, 0.0, 0.0, 0, 0, "F-Curve Modifier Type. Click to make modifier active one."); - else - uiDefBut(block, LABEL, 1, "", 10+40, *yco, 150, 20, NULL, 0.0, 0.0, 0, 0, "F-Curve Modifier Type. Click to make modifier active one."); - - /* 'mute' button */ - uiDefIconButBitS(block, ICONTOG, FMODIFIER_FLAG_MUTED, B_REDR, ICON_MUTE_IPO_OFF, 10+(width-60), *yco-1, 20, 20, &fcm->flag, 0.0, 0.0, 0, 0, "Modifier is temporarily muted (not evaluated)."); - - /* delete button */ - but= uiDefIconBut(block, BUT, B_REDR, ICON_X, 10+(width-30), *yco, 19, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Delete F-Curve Modifier."); - uiButSetFunc(but, delete_fmodifier_cb, fcu, fcm); - - uiBlockSetEmboss(block, UI_EMBOSS); - } - - /* when modifier is expanded, draw settings */ - if (fcm->flag & FMODIFIER_FLAG_EXPANDED) { - /* draw settings for individual modifiers */ - switch (fcm->type) { - case FMODIFIER_TYPE_GENERATOR: /* Generator */ - draw_modifier__generator(block, fcu, fcm, yco, &height, width, active, rb_col); - break; - - case FMODIFIER_TYPE_FN_GENERATOR: /* Built-In Function Generator */ - draw_modifier__fn_generator(block, fcu, fcm, yco, &height, width, active, rb_col); - break; - - case FMODIFIER_TYPE_CYCLES: /* Cycles */ - draw_modifier__cycles(block, fcu, fcm, yco, &height, width, active, rb_col); - break; - - case FMODIFIER_TYPE_ENVELOPE: /* Envelope */ - draw_modifier__envelope(block, fcu, fcm, yco, &height, width, active, rb_col); - break; - - case FMODIFIER_TYPE_LIMITS: /* Limits */ - draw_modifier__limits(block, fcu, fcm, yco, &height, width, active, rb_col); - break; - - case FMODIFIER_TYPE_NOISE: /* Noise */ - draw_modifier__noise(block, fcu, fcm, yco, &height, width, active, rb_col); - break; - - default: /* unknown type */ - height= 96; - //DRAW_BACKDROP(height); // XXX buggy... - break; - } - } - - /* adjust height for new to start */ - (*yco) -= (height + 27); -} - static void graph_panel_modifiers(const bContext *C, Panel *pa) { bAnimListElem *ale; @@ -950,7 +381,7 @@ static void graph_panel_modifiers(const bContext *C, Panel *pa) /* draw each modifier */ for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next) - graph_panel_modifier_draw(block, fcu, fcm, &yco); + ANIM_uiTemplate_fmodifier_draw(block, fcu, fcm, &yco); MEM_freeN(ale); } diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index c0a1c979147..106185085d6 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -174,6 +174,7 @@ extern StructRNA RNA_ExplodeModifier; extern StructRNA RNA_ExpressionController; extern StructRNA RNA_Event; extern StructRNA RNA_FCurve; +extern StructRNA RNA_FCurveSample; extern StructRNA RNA_FileSelectParams; extern StructRNA RNA_FModifier; extern StructRNA RNA_FModifierCycles; diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c index 4a83b80a6cf..826d186516d 100644 --- a/source/blender/makesrna/intern/rna_fcurve.c +++ b/source/blender/makesrna/intern/rna_fcurve.c @@ -230,7 +230,7 @@ static void rna_def_fmodifier_function_generator(BlenderRNA *brna) {0, NULL, 0, NULL, NULL}}; srna= RNA_def_struct(brna, "FModifierFunctionGenerator", "FModifier"); - RNA_def_struct_ui_text(srna, "Built-In Function F-Curve Modifier", "Generates values using a Built-In Function."); + RNA_def_struct_ui_text(srna, "Built-In Function F-Modifier", "Generates values using a Built-In Function."); RNA_def_struct_sdna_from(srna, "FMod_FunctionGenerator", "data"); /* coefficients */ @@ -264,7 +264,7 @@ static void rna_def_fmodifier_envelope(BlenderRNA *brna) //PropertyRNA *prop; srna= RNA_def_struct(brna, "FModifierEnvelope", "FModifier"); - RNA_def_struct_ui_text(srna, "Envelope F-Curve Modifier", "Scales the values of the modified F-Curve."); + RNA_def_struct_ui_text(srna, "Envelope F-Modifier", "Scales the values of the modified F-Curve."); RNA_def_struct_sdna_from(srna, "FMod_Envelope", "data"); } @@ -283,7 +283,7 @@ static void rna_def_fmodifier_cycles(BlenderRNA *brna) {0, NULL, 0, NULL, NULL}}; srna= RNA_def_struct(brna, "FModifierCycles", "FModifier"); - RNA_def_struct_ui_text(srna, "Cycles F-Curve Modifier", "Repeats the values of the modified F-Curve."); + RNA_def_struct_ui_text(srna, "Cycles F-Modifier", "Repeats the values of the modified F-Curve."); RNA_def_struct_sdna_from(srna, "FMod_Cycles", "data"); /* before */ @@ -312,7 +312,7 @@ static void rna_def_fmodifier_python(BlenderRNA *brna) //PropertyRNA *prop; srna= RNA_def_struct(brna, "FModifierPython", "FModifier"); - RNA_def_struct_ui_text(srna, "Python F-Curve Modifier", "Performs user-defined operation on the modified F-Curve."); + RNA_def_struct_ui_text(srna, "Python F-Modifier", "Performs user-defined operation on the modified F-Curve."); RNA_def_struct_sdna_from(srna, "FMod_Python", "data"); } @@ -324,7 +324,7 @@ static void rna_def_fmodifier_limits(BlenderRNA *brna) PropertyRNA *prop; srna= RNA_def_struct(brna, "FModifierLimits", "FModifier"); - RNA_def_struct_ui_text(srna, "Limits F-Curve Modifier", "Limits the time/value ranges of the modified F-Curve."); + RNA_def_struct_ui_text(srna, "Limits F-Modifier", "Limits the time/value ranges of the modified F-Curve."); RNA_def_struct_sdna_from(srna, "FMod_Limits", "data"); prop= RNA_def_property(srna, "use_minimum_x", PROP_BOOLEAN, PROP_NONE); @@ -375,7 +375,7 @@ static void rna_def_fmodifier_noise(BlenderRNA *brna) {0, NULL, 0, NULL, NULL}}; srna= RNA_def_struct(brna, "FModifierNoise", "FModifier"); - RNA_def_struct_ui_text(srna, "Noise F-Curve Modifier", "Gives randomness to the modified F-Curve."); + RNA_def_struct_ui_text(srna, "Noise F-Modifier", "Gives randomness to the modified F-Curve."); RNA_def_struct_sdna_from(srna, "FMod_Noise", "data"); prop= RNA_def_property(srna, "modification", PROP_ENUM, PROP_NONE); @@ -411,7 +411,7 @@ void rna_def_fmodifier(BlenderRNA *brna) /* base struct definition */ srna= RNA_def_struct(brna, "FModifier", NULL); RNA_def_struct_refine_func(srna, "rna_FModifierType_refine"); - RNA_def_struct_ui_text(srna, "FCurve Modifier", "Modifier for values of F-Curve."); + RNA_def_struct_ui_text(srna, "F-Modifier", "Modifier for values of F-Curve."); #if 0 // XXX not used yet /* name */ @@ -509,6 +509,27 @@ void rna_def_channeldriver(BlenderRNA *brna) /* *********************** */ +static void rna_def_fpoint(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna= RNA_def_struct(brna, "FCurveSample", NULL); + RNA_def_struct_sdna(srna, "FPoint"); + RNA_def_struct_ui_text(srna, "F-Curve Sample", "Sample point for F-Curve."); + + /* Boolean values */ + prop= RNA_def_property(srna, "selected", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", 1); + RNA_def_property_ui_text(prop, "Selected", "Selection status"); + + /* Vector value */ + prop= RNA_def_property(srna, "point", PROP_FLOAT, PROP_VECTOR); + RNA_def_property_array(prop, 2); + RNA_def_property_float_sdna(prop, NULL, "vec"); + RNA_def_property_ui_text(prop, "Point", "Point coordinates"); +} + void rna_def_fcurve(BlenderRNA *brna) { StructRNA *srna; @@ -559,7 +580,7 @@ void rna_def_fcurve(BlenderRNA *brna) /* Collections */ prop= RNA_def_property(srna, "sampled_points", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "fpt", "totvert"); - RNA_def_property_struct_type(prop, "CurvePoint"); // XXX FPoints not BPoints here! FPoints are much smaller! + RNA_def_property_struct_type(prop, "FCurveSample"); RNA_def_property_ui_text(prop, "Sampled Points", "Sampled animation data"); prop= RNA_def_property(srna, "keyframe_points", PROP_COLLECTION, PROP_NONE); @@ -577,6 +598,7 @@ void rna_def_fcurve(BlenderRNA *brna) void RNA_def_fcurve(BlenderRNA *brna) { rna_def_fcurve(brna); + rna_def_fpoint(brna); rna_def_drivertarget(brna); rna_def_channeldriver(brna); From f3c47a66b0cb3bb70505ed46522e6c557769eaa5 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 2 Jul 2009 05:25:14 +0000 Subject: [PATCH 078/114] NLA SoC: Separating out F-Modifier API * F-Modifier API is now in its own file in blenkernel * Renamed and refactored these so that they're no dependent on F-Curves, since all they really used was the fcu->modifiers list * Added missing license blocks to a few files --- source/blender/blenkernel/BKE_fcurve.h | 14 +- source/blender/blenkernel/intern/fcurve.c | 1137 +--------------- source/blender/blenkernel/intern/fmodifier.c | 1197 +++++++++++++++++ source/blender/blenkernel/intern/ipo.c | 2 +- source/blender/blenkernel/intern/nla.c | 13 +- source/blender/editors/animation/drivers.c | 31 +- .../blender/editors/animation/fmodifier_ui.c | 21 +- source/blender/editors/animation/keyframing.c | 29 +- source/blender/editors/animation/keyingsets.c | 29 +- .../blender/editors/space_graph/graph_draw.c | 2 +- .../blender/editors/space_graph/graph_edit.c | 4 +- .../blender/editors/space_graph/graph_utils.c | 4 +- 12 files changed, 1310 insertions(+), 1173 deletions(-) create mode 100644 source/blender/blenkernel/intern/fmodifier.c diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h index 5c77e3c2ae4..cfc4e9077f6 100644 --- a/source/blender/blenkernel/BKE_fcurve.h +++ b/source/blender/blenkernel/BKE_fcurve.h @@ -104,15 +104,15 @@ FModifierTypeInfo *get_fmodifier_typeinfo(int type); /* ---------------------- */ -struct FModifier *fcurve_add_modifier(struct FCurve *fcu, int type); -void fcurve_copy_modifiers(ListBase *dst, ListBase *src); -void fcurve_remove_modifier(struct FCurve *fcu, struct FModifier *fcm); -void fcurve_free_modifiers(struct FCurve *fcu); +struct FModifier *add_fmodifier(ListBase *modifiers, int type); +void copy_fmodifiers(ListBase *dst, ListBase *src); +void remove_fmodifier(ListBase *modifiers, struct FModifier *fcm); +void free_fmodifiers(ListBase *modifiers); -struct FModifier *fcurve_find_active_modifier(struct FCurve *fcu); -void fcurve_set_active_modifier(struct FCurve *fcu, struct FModifier *fcm); +struct FModifier *find_active_fmodifier(ListBase *modifiers); +void set_active_fmodifier(ListBase *modifiers, struct FModifier *fcm); -short fcurve_has_suitable_modifier(struct FCurve *fcu, int mtype, short acttype); +short list_has_suitable_fmodifier(ListBase *modifiers, int mtype, short acttype); float evaluate_time_fmodifiers(ListBase *modifiers, struct FCurve *fcu, float cvalue, float evaltime); void evaluate_value_fmodifiers(ListBase *modifiers, struct FCurve *fcu, float *cvalue, float evaltime); diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index e52c63d1b21..4c2ba61fc71 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -56,7 +56,7 @@ #include "RNA_types.h" #ifndef DISABLE_PYTHON -#include "BPY_extern.h" /* for BPY_pydriver_eval() */ +#include "BPY_extern.h" #endif #define SMALL -1.0e-10 @@ -84,7 +84,7 @@ void free_fcurve (FCurve *fcu) /* free extra data - i.e. modifiers, and driver */ fcurve_free_driver(fcu); - fcurve_free_modifiers(fcu); + free_fmodifiers(&fcu->modifiers); /* free f-curve itself */ MEM_freeN(fcu); @@ -140,7 +140,7 @@ FCurve *copy_fcurve (FCurve *fcu) fcu_d->driver= fcurve_copy_driver(fcu_d->driver); /* copy modifiers */ - fcurve_copy_modifiers(&fcu_d->modifiers, &fcu->modifiers); + copy_fmodifiers(&fcu_d->modifiers, &fcu->modifiers); /* return new data */ return fcu_d; @@ -1270,1135 +1270,6 @@ static float fcurve_eval_samples (FCurve *fcu, FPoint *fpts, float evaltime) return cvalue; } -/* ******************************** F-Curve Modifiers ********************************* */ - -/* Template --------------------------- */ - -/* Each modifier defines a set of functions, which will be called at the appropriate - * times. In addition to this, each modifier should have a type-info struct, where - * its functions are attached for use. - */ - -/* Template for type-info data: - * - make a copy of this when creating new modifiers, and just change the functions - * pointed to as necessary - * - although the naming of functions doesn't matter, it would help for code - * readability, to follow the same naming convention as is presented here - * - any functions that a constraint doesn't need to define, don't define - * for such cases, just use NULL - * - these should be defined after all the functions have been defined, so that - * forward-definitions/prototypes don't need to be used! - * - keep this copy #if-def'd so that future constraints can get based off this - */ -#if 0 -static FModifierTypeInfo FMI_MODNAME = { - FMODIFIER_TYPE_MODNAME, /* type */ - sizeof(FMod_ModName), /* size */ - FMI_TYPE_SOME_ACTION, /* action type */ - FMI_REQUIRES_SOME_REQUIREMENT, /* requirements */ - "Modifier Name", /* name */ - "FMod_ModName", /* struct name */ - fcm_modname_free, /* free data */ - fcm_modname_relink, /* relink data */ - fcm_modname_copy, /* copy data */ - fcm_modname_new_data, /* new data */ - fcm_modname_verify, /* verify */ - fcm_modname_time, /* evaluate time */ - fcm_modname_evaluate /* evaluate */ -}; -#endif - -/* Generator F-Curve Modifier --------------------------- */ - -/* Generators available: - * 1) simple polynomial generator: - * - Exanded form - (y = C[0]*(x^(n)) + C[1]*(x^(n-1)) + ... + C[n]) - * - Factorised form - (y = (C[0][0]*x + C[0][1]) * (C[1][0]*x + C[1][1]) * ... * (C[n][0]*x + C[n][1])) - */ - -static void fcm_generator_free (FModifier *fcm) -{ - FMod_Generator *data= (FMod_Generator *)fcm->data; - - /* free polynomial coefficients array */ - if (data->coefficients) - MEM_freeN(data->coefficients); -} - -static void fcm_generator_copy (FModifier *fcm, FModifier *src) -{ - FMod_Generator *gen= (FMod_Generator *)fcm->data; - FMod_Generator *ogen= (FMod_Generator *)src->data; - - /* copy coefficients array? */ - if (ogen->coefficients) - gen->coefficients= MEM_dupallocN(ogen->coefficients); -} - -static void fcm_generator_new_data (void *mdata) -{ - FMod_Generator *data= (FMod_Generator *)mdata; - float *cp; - - /* set default generator to be linear 0-1 (gradient = 1, y-offset = 0) */ - data->poly_order= 1; - data->arraysize= 2; - cp= data->coefficients= MEM_callocN(sizeof(float)*2, "FMod_Generator_Coefs"); - cp[0] = 0; // y-offset - cp[1] = 1; // gradient -} - -static void fcm_generator_verify (FModifier *fcm) -{ - FMod_Generator *data= (FMod_Generator *)fcm->data; - - /* requirements depend on mode */ - switch (data->mode) { - case FCM_GENERATOR_POLYNOMIAL: /* expanded polynomial expression */ - { - /* arraysize needs to be order+1, so resize if not */ - if (data->arraysize != (data->poly_order+1)) { - float *nc; - - /* make new coefficients array, and copy over as much data as can fit */ - nc= MEM_callocN(sizeof(float)*(data->poly_order+1), "FMod_Generator_Coefs"); - - if (data->coefficients) { - if (data->arraysize > (data->poly_order+1)) - memcpy(nc, data->coefficients, sizeof(float)*(data->poly_order+1)); - else - memcpy(nc, data->coefficients, sizeof(float)*data->arraysize); - - /* free the old data */ - MEM_freeN(data->coefficients); - } - - /* set the new data */ - data->coefficients= nc; - data->arraysize= data->poly_order+1; - } - } - break; - - case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* expanded polynomial expression */ - { - /* arraysize needs to be 2*order, so resize if not */ - if (data->arraysize != (data->poly_order * 2)) { - float *nc; - - /* make new coefficients array, and copy over as much data as can fit */ - nc= MEM_callocN(sizeof(float)*(data->poly_order*2), "FMod_Generator_Coefs"); - - if (data->coefficients) { - if (data->arraysize > (data->poly_order * 2)) - memcpy(nc, data->coefficients, sizeof(float)*(data->poly_order * 2)); - else - memcpy(nc, data->coefficients, sizeof(float)*data->arraysize); - - /* free the old data */ - MEM_freeN(data->coefficients); - } - - /* set the new data */ - data->coefficients= nc; - data->arraysize= data->poly_order * 2; - } - } - break; - } -} - -static void fcm_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) -{ - FMod_Generator *data= (FMod_Generator *)fcm->data; - - /* behaviour depends on mode - * NOTE: the data in its default state is fine too - */ - switch (data->mode) { - case FCM_GENERATOR_POLYNOMIAL: /* expanded polynomial expression */ - { - /* we overwrite cvalue with the sum of the polynomial */ - float *powers = MEM_callocN(sizeof(float)*data->arraysize, "Poly Powers"); - float value= 0.0f; - unsigned int i; - - /* for each x^n, precalculate value based on previous one first... this should be - * faster that calling pow() for each entry - */ - for (i=0; i < data->arraysize; i++) { - /* first entry is x^0 = 1, otherwise, calculate based on previous */ - if (i) - powers[i]= powers[i-1] * evaltime; - else - powers[0]= 1; - } - - /* for each coefficient, add to value, which we'll write to *cvalue in one go */ - for (i=0; i < data->arraysize; i++) - value += data->coefficients[i] * powers[i]; - - /* only if something changed, write *cvalue in one go */ - if (data->poly_order) { - if (data->flag & FCM_GENERATOR_ADDITIVE) - *cvalue += value; - else - *cvalue= value; - } - - /* cleanup */ - if (powers) - MEM_freeN(powers); - } - break; - - case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* factorised polynomial */ - { - float value= 1.0f, *cp=NULL; - unsigned int i; - - /* for each coefficient pair, solve for that bracket before accumulating in value by multiplying */ - for (cp=data->coefficients, i=0; (cp) && (i < data->poly_order); cp+=2, i++) - value *= (cp[0]*evaltime + cp[1]); - - /* only if something changed, write *cvalue in one go */ - if (data->poly_order) { - if (data->flag & FCM_GENERATOR_ADDITIVE) - *cvalue += value; - else - *cvalue= value; - } - } - break; - } -} - -static FModifierTypeInfo FMI_GENERATOR = { - FMODIFIER_TYPE_GENERATOR, /* type */ - sizeof(FMod_Generator), /* size */ - FMI_TYPE_GENERATE_CURVE, /* action type */ - FMI_REQUIRES_NOTHING, /* requirements */ - "Generator", /* name */ - "FMod_Generator", /* struct name */ - fcm_generator_free, /* free data */ - fcm_generator_copy, /* copy data */ - fcm_generator_new_data, /* new data */ - fcm_generator_verify, /* verify */ - NULL, /* evaluate time */ - fcm_generator_evaluate /* evaluate */ -}; - -/* Built-In Function Generator F-Curve Modifier --------------------------- */ - -/* This uses the general equation for equations: - * y = amplitude * fn(phase_multiplier*x + phase_offset) + y_offset - * - * where amplitude, phase_multiplier/offset, y_offset are user-defined coefficients, - * x is the evaluation 'time', and 'y' is the resultant value - * - * Functions available are - * sin, cos, tan, sinc (normalised sin), natural log, square root - */ - -static void fcm_fn_generator_new_data (void *mdata) -{ - FMod_FunctionGenerator *data= (FMod_FunctionGenerator *)mdata; - - /* set amplitude and phase multiplier to 1.0f so that something is generated */ - data->amplitude= 1.0f; - data->phase_multiplier= 1.0f; -} - -/* Unary 'normalised sine' function - * y = sin(PI + x) / (PI * x), - * except for x = 0 when y = 1. - */ -static double sinc (double x) -{ - if (fabs(x) < 0.0001) - return 1.0; - else - return sin(M_PI * x) / (M_PI * x); -} - -static void fcm_fn_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) -{ - FMod_FunctionGenerator *data= (FMod_FunctionGenerator *)fcm->data; - double arg= data->phase_multiplier*evaltime + data->phase_offset; - double (*fn)(double v) = NULL; - - /* get function pointer to the func to use: - * WARNING: must perform special argument validation hereto guard against crashes - */ - switch (data->type) - { - /* simple ones */ - case FCM_GENERATOR_FN_SIN: /* sine wave */ - fn= sin; - break; - case FCM_GENERATOR_FN_COS: /* cosine wave */ - fn= cos; - break; - case FCM_GENERATOR_FN_SINC: /* normalised sine wave */ - fn= sinc; - break; - - /* validation required */ - case FCM_GENERATOR_FN_TAN: /* tangent wave */ - { - /* check that argument is not on one of the discontinuities (i.e. 90deg, 270 deg, etc) */ - if IS_EQ(fmod((arg - M_PI_2), M_PI), 0.0) { - if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0) - *cvalue = 0.0f; /* no value possible here */ - } - else - fn= tan; - } - break; - case FCM_GENERATOR_FN_LN: /* natural log */ - { - /* check that value is greater than 1? */ - if (arg > 1.0f) { - fn= log; - } - else { - if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0) - *cvalue = 0.0f; /* no value possible here */ - } - } - break; - case FCM_GENERATOR_FN_SQRT: /* square root */ - { - /* no negative numbers */ - if (arg > 0.0f) { - fn= sqrt; - } - else { - if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0) - *cvalue = 0.0f; /* no value possible here */ - } - } - break; - - default: - printf("Invalid Function-Generator for F-Modifier - %d \n", data->type); - } - - /* execute function callback to set value if appropriate */ - if (fn) { - float value= (float)(data->amplitude*fn(arg) + data->value_offset); - - if (data->flag & FCM_GENERATOR_ADDITIVE) - *cvalue += value; - else - *cvalue= value; - } -} - -static FModifierTypeInfo FMI_FN_GENERATOR = { - FMODIFIER_TYPE_FN_GENERATOR, /* type */ - sizeof(FMod_FunctionGenerator), /* size */ - FMI_TYPE_GENERATE_CURVE, /* action type */ - FMI_REQUIRES_NOTHING, /* requirements */ - "Built-In Function", /* name */ - "FMod_FunctionGenerator", /* struct name */ - NULL, /* free data */ - NULL, /* copy data */ - fcm_fn_generator_new_data, /* new data */ - NULL, /* verify */ - NULL, /* evaluate time */ - fcm_fn_generator_evaluate /* evaluate */ -}; - -/* Envelope F-Curve Modifier --------------------------- */ - -static void fcm_envelope_free (FModifier *fcm) -{ - FMod_Envelope *env= (FMod_Envelope *)fcm->data; - - /* free envelope data array */ - if (env->data) - MEM_freeN(env->data); -} - -static void fcm_envelope_copy (FModifier *fcm, FModifier *src) -{ - FMod_Envelope *env= (FMod_Envelope *)fcm->data; - FMod_Envelope *oenv= (FMod_Envelope *)src->data; - - /* copy envelope data array */ - if (oenv->data) - env->data= MEM_dupallocN(oenv->data); -} - -static void fcm_envelope_new_data (void *mdata) -{ - FMod_Envelope *env= (FMod_Envelope *)mdata; - - /* set default min/max ranges */ - env->min= -1.0f; - env->max= 1.0f; -} - -static void fcm_envelope_verify (FModifier *fcm) -{ - FMod_Envelope *env= (FMod_Envelope *)fcm->data; - - /* if the are points, perform bubble-sort on them, as user may have changed the order */ - if (env->data) { - // XXX todo... - } -} - -static void fcm_envelope_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) -{ - FMod_Envelope *env= (FMod_Envelope *)fcm->data; - FCM_EnvelopeData *fed, *prevfed, *lastfed; - float min=0.0f, max=0.0f, fac=0.0f; - int a; - - /* get pointers */ - if (env->data == NULL) return; - prevfed= env->data; - fed= prevfed + 1; - lastfed= prevfed + (env->totvert-1); - - /* get min/max values for envelope at evaluation time (relative to mid-value) */ - if (prevfed->time >= evaltime) { - /* before or on first sample, so just extend value */ - min= prevfed->min; - max= prevfed->max; - } - else if (lastfed->time <= evaltime) { - /* after or on last sample, so just extend value */ - min= lastfed->min; - max= lastfed->max; - } - else { - /* evaltime occurs somewhere between segments */ - // TODO: implement binary search for this to make it faster? - for (a=0; prevfed && fed && (a < env->totvert-1); a++, prevfed=fed, fed++) { - /* evaltime occurs within the interval defined by these two envelope points */ - if ((prevfed->time <= evaltime) && (fed->time >= evaltime)) { - float afac, bfac, diff; - - diff= fed->time - prevfed->time; - afac= (evaltime - prevfed->time) / diff; - bfac= (fed->time - evaltime) / diff; - - min= bfac*prevfed->min + afac*fed->min; - max= bfac*prevfed->max + afac*fed->max; - - break; - } - } - } - - /* adjust *cvalue - * - fac is the ratio of how the current y-value corresponds to the reference range - * - thus, the new value is found by mapping the old range to the new! - */ - fac= (*cvalue - (env->midval + env->min)) / (env->max - env->min); - *cvalue= min + fac*(max - min); -} - -static FModifierTypeInfo FMI_ENVELOPE = { - FMODIFIER_TYPE_ENVELOPE, /* type */ - sizeof(FMod_Envelope), /* size */ - FMI_TYPE_REPLACE_VALUES, /* action type */ - 0, /* requirements */ - "Envelope", /* name */ - "FMod_Envelope", /* struct name */ - fcm_envelope_free, /* free data */ - fcm_envelope_copy, /* copy data */ - fcm_envelope_new_data, /* new data */ - fcm_envelope_verify, /* verify */ - NULL, /* evaluate time */ - fcm_envelope_evaluate /* evaluate */ -}; - -/* Cycles F-Curve Modifier --------------------------- */ - -/* This modifier changes evaltime to something that exists within the curve's frame-range, - * then re-evaluates modifier stack up to this point using the new time. This re-entrant behaviour - * is very likely to be more time-consuming than the original approach... (which was tighly integrated into - * the calculation code...). - * - * NOTE: this needs to be at the start of the stack to be of use, as it needs to know the extents of the keyframes/sample-data - * Possible TODO - store length of cycle information that can be initialised from the extents of the keyframes/sample-data, and adjusted - * as appropriate - */ - -/* temp data used during evaluation */ -typedef struct tFCMED_Cycles { - float cycyofs; /* y-offset to apply */ -} tFCMED_Cycles; - -static void fcm_cycles_new_data (void *mdata) -{ - FMod_Cycles *data= (FMod_Cycles *)mdata; - - /* turn on cycles by default */ - data->before_mode= data->after_mode= FCM_EXTRAPOLATE_CYCLIC; -} - -static float fcm_cycles_time (FCurve *fcu, FModifier *fcm, float cvalue, float evaltime) -{ - FMod_Cycles *data= (FMod_Cycles *)fcm->data; - float prevkey[2], lastkey[2], cycyofs=0.0f; - short side=0, mode=0; - int cycles=0; - - /* check if modifier is first in stack, otherwise disable ourself... */ - // FIXME... - if (fcm->prev) { - fcm->flag |= FMODIFIER_FLAG_DISABLED; - return evaltime; - } - - /* calculate new evaltime due to cyclic interpolation */ - if (fcu && fcu->bezt) { - BezTriple *prevbezt= fcu->bezt; - BezTriple *lastbezt= prevbezt + fcu->totvert-1; - - prevkey[0]= prevbezt->vec[1][0]; - prevkey[1]= prevbezt->vec[1][1]; - - lastkey[0]= lastbezt->vec[1][0]; - lastkey[1]= lastbezt->vec[1][1]; - } - else if (fcu && fcu->fpt) { - FPoint *prevfpt= fcu->fpt; - FPoint *lastfpt= prevfpt + fcu->totvert-1; - - prevkey[0]= prevfpt->vec[0]; - prevkey[1]= prevfpt->vec[1]; - - lastkey[0]= lastfpt->vec[0]; - lastkey[1]= lastfpt->vec[1]; - } - else - return evaltime; - - /* check if modifier will do anything - * 1) if in data range, definitely don't do anything - * 2) if before first frame or after last frame, make sure some cycling is in use - */ - if (evaltime < prevkey[0]) { - if (data->before_mode) { - side= -1; - mode= data->before_mode; - cycles= data->before_cycles; - } - } - else if (evaltime > lastkey[0]) { - if (data->after_mode) { - side= 1; - mode= data->after_mode; - cycles= data->after_cycles; - } - } - if ELEM(0, side, mode) - return evaltime; - - /* find relative place within a cycle */ - { - float cycdx=0, cycdy=0, ofs=0; - float cycle= 0; - - /* ofs is start frame of cycle */ - ofs= prevkey[0]; - - /* calculate period and amplitude (total height) of a cycle */ - cycdx= lastkey[0] - prevkey[0]; - cycdy= lastkey[1] - prevkey[1]; - - /* check if cycle is infinitely small, to be point of being impossible to use */ - if (cycdx == 0) - return evaltime; - - /* calculate the 'number' of the cycle */ - cycle= ((float)side * (evaltime - ofs) / cycdx); - - /* check that cyclic is still enabled for the specified time */ - if (cycles == 0) { - /* catch this case so that we don't exit when we have cycles=0 - * as this indicates infinite cycles... - */ - } - else if (cycle > (cycles+1)) { - /* we are too far away from range to evaluate - * TODO: but we should still hold last value... - */ - return evaltime; - } - - /* check if 'cyclic extrapolation', and thus calculate y-offset for this cycle */ - if (mode == FCM_EXTRAPOLATE_CYCLIC_OFFSET) { - cycyofs = (float)floor((evaltime - ofs) / cycdx); - cycyofs *= cycdy; - } - - /* calculate where in the cycle we are (overwrite evaltime to reflect this) */ - if ((mode == FCM_EXTRAPOLATE_MIRROR) && ((int)(cycle) % 2)) { - /* when 'mirror' option is used and cycle number is odd, this cycle is played in reverse - * - for 'before' extrapolation, we need to flip in a different way, otherwise values past - * then end of the curve get referenced (result of fmod will be negative, and with different phase) - */ - if (side < 0) - evaltime= (float)(prevkey[0] - fmod(evaltime-ofs, cycdx)); - else - evaltime= (float)(lastkey[0] - fmod(evaltime-ofs, cycdx)); - } - else { - /* the cycle is played normally... */ - evaltime= (float)(fmod(evaltime-ofs, cycdx) + ofs); - } - if (evaltime < ofs) evaltime += cycdx; - } - - /* store temp data if needed */ - if (mode == FCM_EXTRAPOLATE_CYCLIC_OFFSET) { - tFCMED_Cycles *edata; - - /* for now, this is just a float, but we could get more stuff... */ - fcm->edata= edata= MEM_callocN(sizeof(tFCMED_Cycles), "tFCMED_Cycles"); - edata->cycyofs= cycyofs; - } - - /* return the new frame to evaluate */ - return evaltime; -} - -static void fcm_cycles_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) -{ - tFCMED_Cycles *edata= (tFCMED_Cycles *)fcm->edata; - - /* use temp data */ - if (edata) { - /* add cyclic offset - no need to check for now, otherwise the data wouldn't exist! */ - *cvalue += edata->cycyofs; - - /* free temp data */ - MEM_freeN(edata); - fcm->edata= NULL; - } -} - -static FModifierTypeInfo FMI_CYCLES = { - FMODIFIER_TYPE_CYCLES, /* type */ - sizeof(FMod_Cycles), /* size */ - FMI_TYPE_EXTRAPOLATION, /* action type */ - FMI_REQUIRES_ORIGINAL_DATA, /* requirements */ - "Cycles", /* name */ - "FMod_Cycles", /* struct name */ - NULL, /* free data */ - NULL, /* copy data */ - fcm_cycles_new_data, /* new data */ - NULL /*fcm_cycles_verify*/, /* verify */ - fcm_cycles_time, /* evaluate time */ - fcm_cycles_evaluate /* evaluate */ -}; - -/* Noise F-Curve Modifier --------------------------- */ - -static void fcm_noise_new_data (void *mdata) -{ - FMod_Noise *data= (FMod_Noise *)mdata; - - /* defaults */ - data->size= 1.0f; - data->strength= 1.0f; - data->phase= 1.0f; - data->depth = 0; - data->modification = FCM_NOISE_MODIF_REPLACE; -} - -static void fcm_noise_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) -{ - FMod_Noise *data= (FMod_Noise *)fcm->data; - float noise; - - noise = BLI_turbulence(data->size, evaltime, data->phase, 0.f, data->depth); - - switch (data->modification) { - case FCM_NOISE_MODIF_ADD: - *cvalue= *cvalue + noise * data->strength; - break; - case FCM_NOISE_MODIF_SUBTRACT: - *cvalue= *cvalue - noise * data->strength; - break; - case FCM_NOISE_MODIF_MULTIPLY: - *cvalue= *cvalue * noise * data->strength; - break; - case FCM_NOISE_MODIF_REPLACE: - default: - *cvalue= *cvalue + (noise - 0.5f) * data->strength; - break; - } -} - -static FModifierTypeInfo FMI_NOISE = { - FMODIFIER_TYPE_NOISE, /* type */ - sizeof(FMod_Noise), /* size */ - FMI_TYPE_REPLACE_VALUES, /* action type */ - 0, /* requirements */ - "Noise", /* name */ - "FMod_Noise", /* struct name */ - NULL, /* free data */ - NULL, /* copy data */ - fcm_noise_new_data, /* new data */ - NULL /*fcm_noise_verify*/, /* verify */ - NULL, /* evaluate time */ - fcm_noise_evaluate /* evaluate */ -}; - -/* Filter F-Curve Modifier --------------------------- */ - -#if 0 // XXX not yet implemented -static FModifierTypeInfo FMI_FILTER = { - FMODIFIER_TYPE_FILTER, /* type */ - sizeof(FMod_Filter), /* size */ - FMI_TYPE_REPLACE_VALUES, /* action type */ - 0, /* requirements */ - "Filter", /* name */ - "FMod_Filter", /* struct name */ - NULL, /* free data */ - NULL, /* copy data */ - NULL, /* new data */ - NULL /*fcm_filter_verify*/, /* verify */ - NULL, /* evlauate time */ - fcm_filter_evaluate /* evaluate */ -}; -#endif // XXX not yet implemented - - -/* Python F-Curve Modifier --------------------------- */ - -static void fcm_python_free (FModifier *fcm) -{ - FMod_Python *data= (FMod_Python *)fcm->data; - - /* id-properties */ - IDP_FreeProperty(data->prop); - MEM_freeN(data->prop); -} - -static void fcm_python_new_data (void *mdata) -{ - FMod_Python *data= (FMod_Python *)mdata; - - /* everything should be set correctly by calloc, except for the prop->type constant.*/ - data->prop = MEM_callocN(sizeof(IDProperty), "PyFModifierProps"); - data->prop->type = IDP_GROUP; -} - -static void fcm_python_copy (FModifier *fcm, FModifier *src) -{ - FMod_Python *pymod = (FMod_Python *)fcm->data; - FMod_Python *opymod = (FMod_Python *)src->data; - - pymod->prop = IDP_CopyProperty(opymod->prop); -} - -static void fcm_python_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) -{ -#ifndef DISABLE_PYTHON - //FMod_Python *data= (FMod_Python *)fcm->data; - - /* FIXME... need to implement this modifier... - * It will need it execute a script using the custom properties - */ -#endif /* DISABLE_PYTHON */ -} - -static FModifierTypeInfo FMI_PYTHON = { - FMODIFIER_TYPE_PYTHON, /* type */ - sizeof(FMod_Python), /* size */ - FMI_TYPE_GENERATE_CURVE, /* action type */ - FMI_REQUIRES_RUNTIME_CHECK, /* requirements */ - "Python", /* name */ - "FMod_Python", /* struct name */ - fcm_python_free, /* free data */ - fcm_python_copy, /* copy data */ - fcm_python_new_data, /* new data */ - NULL /*fcm_python_verify*/, /* verify */ - NULL /*fcm_python_time*/, /* evaluate time */ - fcm_python_evaluate /* evaluate */ -}; - - -/* Limits F-Curve Modifier --------------------------- */ - -static float fcm_limits_time (FCurve *fcu, FModifier *fcm, float cvalue, float evaltime) -{ - FMod_Limits *data= (FMod_Limits *)fcm->data; - - /* check for the time limits */ - if ((data->flag & FCM_LIMIT_XMIN) && (evaltime < data->rect.xmin)) - return data->rect.xmin; - if ((data->flag & FCM_LIMIT_XMAX) && (evaltime > data->rect.xmax)) - return data->rect.xmax; - - /* modifier doesn't change time */ - return evaltime; -} - -static void fcm_limits_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) -{ - FMod_Limits *data= (FMod_Limits *)fcm->data; - - /* value limits now */ - if ((data->flag & FCM_LIMIT_YMIN) && (*cvalue < data->rect.ymin)) - *cvalue= data->rect.ymin; - if ((data->flag & FCM_LIMIT_YMAX) && (*cvalue > data->rect.ymax)) - *cvalue= data->rect.ymax; -} - -static FModifierTypeInfo FMI_LIMITS = { - FMODIFIER_TYPE_LIMITS, /* type */ - sizeof(FMod_Limits), /* size */ - FMI_TYPE_GENERATE_CURVE, /* action type */ /* XXX... err... */ - FMI_REQUIRES_RUNTIME_CHECK, /* requirements */ - "Limits", /* name */ - "FMod_Limits", /* struct name */ - NULL, /* free data */ - NULL, /* copy data */ - NULL, /* new data */ - NULL, /* verify */ - fcm_limits_time, /* evaluate time */ - fcm_limits_evaluate /* evaluate */ -}; - -/* F-Curve Modifier API --------------------------- */ -/* All of the F-Curve Modifier api functions use FModifierTypeInfo structs to carry out - * and operations that involve F-Curve modifier specific code. - */ - -/* These globals only ever get directly accessed in this file */ -static FModifierTypeInfo *fmodifiersTypeInfo[FMODIFIER_NUM_TYPES]; -static short FMI_INIT= 1; /* when non-zero, the list needs to be updated */ - -/* This function only gets called when FMI_INIT is non-zero */ -static void fmods_init_typeinfo () -{ - fmodifiersTypeInfo[0]= NULL; /* 'Null' F-Curve Modifier */ - fmodifiersTypeInfo[1]= &FMI_GENERATOR; /* Generator F-Curve Modifier */ - fmodifiersTypeInfo[2]= &FMI_FN_GENERATOR; /* Built-In Function Generator F-Curve Modifier */ - fmodifiersTypeInfo[3]= &FMI_ENVELOPE; /* Envelope F-Curve Modifier */ - fmodifiersTypeInfo[4]= &FMI_CYCLES; /* Cycles F-Curve Modifier */ - fmodifiersTypeInfo[5]= &FMI_NOISE; /* Apply-Noise F-Curve Modifier */ - fmodifiersTypeInfo[6]= NULL/*&FMI_FILTER*/; /* Filter F-Curve Modifier */ // XXX unimplemented - fmodifiersTypeInfo[7]= &FMI_PYTHON; /* Custom Python F-Curve Modifier */ - fmodifiersTypeInfo[8]= &FMI_LIMITS; /* Limits F-Curve Modifier */ -} - -/* This function should be used for getting the appropriate type-info when only - * a F-Curve modifier type is known - */ -FModifierTypeInfo *get_fmodifier_typeinfo (int type) -{ - /* initialise the type-info list? */ - if (FMI_INIT) { - fmods_init_typeinfo(); - FMI_INIT = 0; - } - - /* only return for valid types */ - if ( (type >= FMODIFIER_TYPE_NULL) && - (type <= FMODIFIER_NUM_TYPES ) ) - { - /* there shouldn't be any segfaults here... */ - return fmodifiersTypeInfo[type]; - } - else { - printf("No valid F-Curve Modifier type-info data available. Type = %i \n", type); - } - - return NULL; -} - -/* This function should always be used to get the appropriate type-info, as it - * has checks which prevent segfaults in some weird cases. - */ -FModifierTypeInfo *fmodifier_get_typeinfo (FModifier *fcm) -{ - /* only return typeinfo for valid modifiers */ - if (fcm) - return get_fmodifier_typeinfo(fcm->type); - else - return NULL; -} - -/* API --------------------------- */ - -/* Add a new F-Curve Modifier to the given F-Curve of a certain type */ -FModifier *fcurve_add_modifier (FCurve *fcu, int type) -{ - FModifierTypeInfo *fmi= get_fmodifier_typeinfo(type); - FModifier *fcm; - - /* sanity checks */ - if ELEM(NULL, fcu, fmi) - return NULL; - - /* special checks for whether modifier can be added */ - if ((fcu->modifiers.first) && (type == FMODIFIER_TYPE_CYCLES)) { - /* cycles modifier must be first in stack, so for now, don't add if it can't be */ - // TODO: perhaps there is some better way, but for now, - printf("Error: Cannot add 'Cycles' modifier to F-Curve, as 'Cycles' modifier can only be first in stack. \n"); - return NULL; - } - - /* add modifier itself */ - fcm= MEM_callocN(sizeof(FModifier), "F-Curve Modifier"); - fcm->type = type; - fcm->flag = FMODIFIER_FLAG_EXPANDED; - BLI_addtail(&fcu->modifiers, fcm); - - /* add modifier's data */ - fcm->data= MEM_callocN(fmi->size, fmi->structName); - - /* init custom settings if necessary */ - if (fmi->new_data) - fmi->new_data(fcm->data); - - /* return modifier for further editing */ - return fcm; -} - -/* Duplicate all of the F-Curve Modifiers in the Modifier stacks */ -void fcurve_copy_modifiers (ListBase *dst, ListBase *src) -{ - FModifier *fcm, *srcfcm; - - if ELEM(NULL, dst, src) - return; - - dst->first= dst->last= NULL; - BLI_duplicatelist(dst, src); - - for (fcm=dst->first, srcfcm=src->first; fcm && srcfcm; srcfcm=srcfcm->next, fcm=fcm->next) { - FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); - - /* make a new copy of the F-Modifier's data */ - fcm->data = MEM_dupallocN(fcm->data); - - /* only do specific constraints if required */ - if (fmi && fmi->copy_data) - fmi->copy_data(fcm, srcfcm); - } -} - -/* Remove and free the given F-Curve Modifier from the given F-Curve's stack */ -void fcurve_remove_modifier (FCurve *fcu, FModifier *fcm) -{ - FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); - - /* sanity check */ - if (fcm == NULL) - return; - - /* free modifier's special data (stored inside fcm->data) */ - if (fcm->data) { - if (fmi && fmi->free_data) - fmi->free_data(fcm); - - /* free modifier's data (fcm->data) */ - MEM_freeN(fcm->data); - } - - /* remove modifier from stack */ - if (fcu) - BLI_freelinkN(&fcu->modifiers, fcm); - else { - // XXX this case can probably be removed some day, as it shouldn't happen... - printf("fcurve_remove_modifier() - no fcurve \n"); - MEM_freeN(fcm); - } -} - -/* Remove all of a given F-Curve's modifiers */ -void fcurve_free_modifiers (FCurve *fcu) -{ - FModifier *fcm, *fmn; - - /* sanity check */ - if (fcu == NULL) - return; - - /* free each modifier in order - modifier is unlinked from list and freed */ - for (fcm= fcu->modifiers.first; fcm; fcm= fmn) { - fmn= fcm->next; - fcurve_remove_modifier(fcu, fcm); - } -} - -/* Find the active F-Curve Modifier */ -FModifier *fcurve_find_active_modifier (FCurve *fcu) -{ - FModifier *fcm; - - /* sanity checks */ - if ELEM(NULL, fcu, fcu->modifiers.first) - return NULL; - - /* loop over modifiers until 'active' one is found */ - for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next) { - if (fcm->flag & FMODIFIER_FLAG_ACTIVE) - return fcm; - } - - /* no modifier is active */ - return NULL; -} - -/* Set the active F-Curve Modifier */ -void fcurve_set_active_modifier (FCurve *fcu, FModifier *fcm) -{ - FModifier *fm; - - /* sanity checks */ - if ELEM(NULL, fcu, fcu->modifiers.first) - return; - - /* deactivate all, and set current one active */ - for (fm= fcu->modifiers.first; fm; fm= fm->next) - fm->flag &= ~FMODIFIER_FLAG_ACTIVE; - - /* make given modifier active */ - if (fcm) - fcm->flag |= FMODIFIER_FLAG_ACTIVE; -} - -/* Do we have any modifiers which match certain criteria - * - mtype - type of modifier (if 0, doesn't matter) - * - acttype - type of action to perform (if -1, doesn't matter) - */ -short fcurve_has_suitable_modifier (FCurve *fcu, int mtype, short acttype) -{ - FModifier *fcm; - - /* if there are no specific filtering criteria, just skip */ - if ((mtype == 0) && (acttype == 0)) - return (fcu && fcu->modifiers.first); - - /* sanity checks */ - if ELEM(NULL, fcu, fcu->modifiers.first) - return 0; - - /* find the first mdifier fitting these criteria */ - for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next) { - FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); - short mOk=1, aOk=1; /* by default 1, so that when only one test, won't fail */ - - /* check if applicable ones are fullfilled */ - if (mtype) - mOk= (fcm->type == mtype); - if (acttype > -1) - aOk= (fmi->acttype == acttype); - - /* if both are ok, we've found a hit */ - if (mOk && aOk) - return 1; - } - - /* no matches */ - return 0; -} - -/* Evaluation API --------------------------- */ - -/* evaluate time modifications imposed by some F-Curve Modifiers - * - this step acts as an optimisation to prevent the F-Curve stack being evaluated - * several times by modifiers requesting the time be modified, as the final result - * would have required using the modified time - * - modifiers only ever recieve the unmodified time, as subsequent modifiers should be - * working on the 'global' result of the modified curve, not some localised segment, - * so nevaltime gets set to whatever the last time-modifying modifier likes... - * - we start from the end of the stack, as only the last one matters for now - */ -float evaluate_time_fmodifiers (ListBase *modifiers, FCurve *fcu, float cvalue, float evaltime) -{ - FModifier *fcm; - float m_evaltime= evaltime; - - /* sanity checks */ - if ELEM(NULL, modifiers, modifiers->first) - return evaltime; - - /* find the first modifier from end of stack that modifies time, and calculate the time the modifier - * would calculate time at - */ - for (fcm= fcu->modifiers.last; fcm; fcm= fcm->prev) { - FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); - - /* only evaluate if there's a callback for this */ - // TODO: implement the 'influence' control feature... - if (fmi && fmi->evaluate_modifier_time) { - if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0) - m_evaltime= fmi->evaluate_modifier_time(fcu, fcm, cvalue, evaltime); - break; - } - } - - /* return the modified evaltime */ - return m_evaltime; -} - -/* Evalautes the given set of F-Curve Modifiers using the given data - * Should only be called after evaluate_time_fmodifiers() has been called... - */ -void evaluate_value_fmodifiers (ListBase *modifiers, FCurve *fcu, float *cvalue, float evaltime) -{ - FModifier *fcm; - - /* sanity checks */ - if ELEM(NULL, modifiers, modifiers->first) - return; - - /* evaluate modifiers */ - for (fcm= modifiers->first; fcm; fcm= fcm->next) { - FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); - - /* only evaluate if there's a callback for this */ - // TODO: implement the 'influence' control feature... - if (fmi && fmi->evaluate_modifier) { - if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0) - fmi->evaluate_modifier(fcu, fcm, cvalue, evaltime); - } - } -} - - -/* Bake modifiers for given F-Curve to curve sample data, in the frame range defined - * by start and end (inclusive). - */ -void fcurve_bake_modifiers (FCurve *fcu, int start, int end) -{ - ChannelDriver *driver; - - /* sanity checks */ - // TODO: make these tests report errors using reports not printf's - if ELEM(NULL, fcu, fcu->modifiers.first) { - printf("Error: No F-Curve with F-Curve Modifiers to Bake\n"); - return; - } - - /* temporarily, disable driver while we sample, so that they don't influence the outcome */ - driver= fcu->driver; - fcu->driver= NULL; - - /* bake the modifiers, by sampling the curve at each frame */ - fcurve_store_samples(fcu, NULL, start, end, fcurve_samplingcb_evalcurve); - - /* free the modifiers now */ - fcurve_free_modifiers(fcu); - - /* restore driver */ - fcu->driver= driver; -} - /* ***************************** F-Curve - Evaluation ********************************* */ /* Evaluate and return the value of the given F-Curve at the specified frame ("evaltime") @@ -2450,7 +1321,7 @@ void calculate_fcurve (FCurve *fcu, float ctime) * any data which warrants this... */ if ( (fcu->totvert) || (fcu->driver && !(fcu->driver->flag & DRIVER_FLAG_INVALID)) || - fcurve_has_suitable_modifier(fcu, 0, FMI_TYPE_GENERATE_CURVE) ) + list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) ) { /* calculate and set curval (evaluates driver too if necessary) */ fcu->curval= evaluate_fcurve(fcu, ctime); diff --git a/source/blender/blenkernel/intern/fmodifier.c b/source/blender/blenkernel/intern/fmodifier.c new file mode 100644 index 00000000000..aa5214979d9 --- /dev/null +++ b/source/blender/blenkernel/intern/fmodifier.c @@ -0,0 +1,1197 @@ +/** + * $Id: fcurve.c 21299 2009-07-02 02:12:37Z aligorith $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung + * All rights reserved. + * + * Contributor(s): Joshua Leung (full recode) + * + * ***** END GPL LICENSE BLOCK ***** + */ + + +#include +#include +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "MEM_guardedalloc.h" + +#include "DNA_anim_types.h" + +#include "BLI_blenlib.h" +#include "BLI_arithb.h" +#include "BLI_noise.h" + +#include "BKE_fcurve.h" +#include "BKE_curve.h" +#include "BKE_global.h" +#include "BKE_idprop.h" +#include "BKE_utildefines.h" + +#include "RNA_access.h" +#include "RNA_types.h" + +#ifndef DISABLE_PYTHON +#include "BPY_extern.h" /* for BPY_pydriver_eval() */ +#endif + +#define SMALL -1.0e-10 +#define SELECT 1 + +/* ******************************** F-Modifiers ********************************* */ + +/* Info ------------------------------- */ + +/* F-Modifiers are modifiers which operate on F-Curves. However, they can also be defined + * on NLA-Strips to affect all of the F-Curves referenced by the NLA-Strip. + */ + +/* Template --------------------------- */ + +/* Each modifier defines a set of functions, which will be called at the appropriate + * times. In addition to this, each modifier should have a type-info struct, where + * its functions are attached for use. + */ + +/* Template for type-info data: + * - make a copy of this when creating new modifiers, and just change the functions + * pointed to as necessary + * - although the naming of functions doesn't matter, it would help for code + * readability, to follow the same naming convention as is presented here + * - any functions that a constraint doesn't need to define, don't define + * for such cases, just use NULL + * - these should be defined after all the functions have been defined, so that + * forward-definitions/prototypes don't need to be used! + * - keep this copy #if-def'd so that future constraints can get based off this + */ +#if 0 +static FModifierTypeInfo FMI_MODNAME = { + FMODIFIER_TYPE_MODNAME, /* type */ + sizeof(FMod_ModName), /* size */ + FMI_TYPE_SOME_ACTION, /* action type */ + FMI_REQUIRES_SOME_REQUIREMENT, /* requirements */ + "Modifier Name", /* name */ + "FMod_ModName", /* struct name */ + fcm_modname_free, /* free data */ + fcm_modname_relink, /* relink data */ + fcm_modname_copy, /* copy data */ + fcm_modname_new_data, /* new data */ + fcm_modname_verify, /* verify */ + fcm_modname_time, /* evaluate time */ + fcm_modname_evaluate /* evaluate */ +}; +#endif + +/* Generator F-Curve Modifier --------------------------- */ + +/* Generators available: + * 1) simple polynomial generator: + * - Exanded form - (y = C[0]*(x^(n)) + C[1]*(x^(n-1)) + ... + C[n]) + * - Factorised form - (y = (C[0][0]*x + C[0][1]) * (C[1][0]*x + C[1][1]) * ... * (C[n][0]*x + C[n][1])) + */ + +static void fcm_generator_free (FModifier *fcm) +{ + FMod_Generator *data= (FMod_Generator *)fcm->data; + + /* free polynomial coefficients array */ + if (data->coefficients) + MEM_freeN(data->coefficients); +} + +static void fcm_generator_copy (FModifier *fcm, FModifier *src) +{ + FMod_Generator *gen= (FMod_Generator *)fcm->data; + FMod_Generator *ogen= (FMod_Generator *)src->data; + + /* copy coefficients array? */ + if (ogen->coefficients) + gen->coefficients= MEM_dupallocN(ogen->coefficients); +} + +static void fcm_generator_new_data (void *mdata) +{ + FMod_Generator *data= (FMod_Generator *)mdata; + float *cp; + + /* set default generator to be linear 0-1 (gradient = 1, y-offset = 0) */ + data->poly_order= 1; + data->arraysize= 2; + cp= data->coefficients= MEM_callocN(sizeof(float)*2, "FMod_Generator_Coefs"); + cp[0] = 0; // y-offset + cp[1] = 1; // gradient +} + +static void fcm_generator_verify (FModifier *fcm) +{ + FMod_Generator *data= (FMod_Generator *)fcm->data; + + /* requirements depend on mode */ + switch (data->mode) { + case FCM_GENERATOR_POLYNOMIAL: /* expanded polynomial expression */ + { + /* arraysize needs to be order+1, so resize if not */ + if (data->arraysize != (data->poly_order+1)) { + float *nc; + + /* make new coefficients array, and copy over as much data as can fit */ + nc= MEM_callocN(sizeof(float)*(data->poly_order+1), "FMod_Generator_Coefs"); + + if (data->coefficients) { + if (data->arraysize > (data->poly_order+1)) + memcpy(nc, data->coefficients, sizeof(float)*(data->poly_order+1)); + else + memcpy(nc, data->coefficients, sizeof(float)*data->arraysize); + + /* free the old data */ + MEM_freeN(data->coefficients); + } + + /* set the new data */ + data->coefficients= nc; + data->arraysize= data->poly_order+1; + } + } + break; + + case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* expanded polynomial expression */ + { + /* arraysize needs to be 2*order, so resize if not */ + if (data->arraysize != (data->poly_order * 2)) { + float *nc; + + /* make new coefficients array, and copy over as much data as can fit */ + nc= MEM_callocN(sizeof(float)*(data->poly_order*2), "FMod_Generator_Coefs"); + + if (data->coefficients) { + if (data->arraysize > (data->poly_order * 2)) + memcpy(nc, data->coefficients, sizeof(float)*(data->poly_order * 2)); + else + memcpy(nc, data->coefficients, sizeof(float)*data->arraysize); + + /* free the old data */ + MEM_freeN(data->coefficients); + } + + /* set the new data */ + data->coefficients= nc; + data->arraysize= data->poly_order * 2; + } + } + break; + } +} + +static void fcm_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) +{ + FMod_Generator *data= (FMod_Generator *)fcm->data; + + /* behaviour depends on mode + * NOTE: the data in its default state is fine too + */ + switch (data->mode) { + case FCM_GENERATOR_POLYNOMIAL: /* expanded polynomial expression */ + { + /* we overwrite cvalue with the sum of the polynomial */ + float *powers = MEM_callocN(sizeof(float)*data->arraysize, "Poly Powers"); + float value= 0.0f; + unsigned int i; + + /* for each x^n, precalculate value based on previous one first... this should be + * faster that calling pow() for each entry + */ + for (i=0; i < data->arraysize; i++) { + /* first entry is x^0 = 1, otherwise, calculate based on previous */ + if (i) + powers[i]= powers[i-1] * evaltime; + else + powers[0]= 1; + } + + /* for each coefficient, add to value, which we'll write to *cvalue in one go */ + for (i=0; i < data->arraysize; i++) + value += data->coefficients[i] * powers[i]; + + /* only if something changed, write *cvalue in one go */ + if (data->poly_order) { + if (data->flag & FCM_GENERATOR_ADDITIVE) + *cvalue += value; + else + *cvalue= value; + } + + /* cleanup */ + if (powers) + MEM_freeN(powers); + } + break; + + case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* factorised polynomial */ + { + float value= 1.0f, *cp=NULL; + unsigned int i; + + /* for each coefficient pair, solve for that bracket before accumulating in value by multiplying */ + for (cp=data->coefficients, i=0; (cp) && (i < data->poly_order); cp+=2, i++) + value *= (cp[0]*evaltime + cp[1]); + + /* only if something changed, write *cvalue in one go */ + if (data->poly_order) { + if (data->flag & FCM_GENERATOR_ADDITIVE) + *cvalue += value; + else + *cvalue= value; + } + } + break; + } +} + +static FModifierTypeInfo FMI_GENERATOR = { + FMODIFIER_TYPE_GENERATOR, /* type */ + sizeof(FMod_Generator), /* size */ + FMI_TYPE_GENERATE_CURVE, /* action type */ + FMI_REQUIRES_NOTHING, /* requirements */ + "Generator", /* name */ + "FMod_Generator", /* struct name */ + fcm_generator_free, /* free data */ + fcm_generator_copy, /* copy data */ + fcm_generator_new_data, /* new data */ + fcm_generator_verify, /* verify */ + NULL, /* evaluate time */ + fcm_generator_evaluate /* evaluate */ +}; + +/* Built-In Function Generator F-Curve Modifier --------------------------- */ + +/* This uses the general equation for equations: + * y = amplitude * fn(phase_multiplier*x + phase_offset) + y_offset + * + * where amplitude, phase_multiplier/offset, y_offset are user-defined coefficients, + * x is the evaluation 'time', and 'y' is the resultant value + * + * Functions available are + * sin, cos, tan, sinc (normalised sin), natural log, square root + */ + +static void fcm_fn_generator_new_data (void *mdata) +{ + FMod_FunctionGenerator *data= (FMod_FunctionGenerator *)mdata; + + /* set amplitude and phase multiplier to 1.0f so that something is generated */ + data->amplitude= 1.0f; + data->phase_multiplier= 1.0f; +} + +/* Unary 'normalised sine' function + * y = sin(PI + x) / (PI * x), + * except for x = 0 when y = 1. + */ +static double sinc (double x) +{ + if (fabs(x) < 0.0001) + return 1.0; + else + return sin(M_PI * x) / (M_PI * x); +} + +static void fcm_fn_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) +{ + FMod_FunctionGenerator *data= (FMod_FunctionGenerator *)fcm->data; + double arg= data->phase_multiplier*evaltime + data->phase_offset; + double (*fn)(double v) = NULL; + + /* get function pointer to the func to use: + * WARNING: must perform special argument validation hereto guard against crashes + */ + switch (data->type) + { + /* simple ones */ + case FCM_GENERATOR_FN_SIN: /* sine wave */ + fn= sin; + break; + case FCM_GENERATOR_FN_COS: /* cosine wave */ + fn= cos; + break; + case FCM_GENERATOR_FN_SINC: /* normalised sine wave */ + fn= sinc; + break; + + /* validation required */ + case FCM_GENERATOR_FN_TAN: /* tangent wave */ + { + /* check that argument is not on one of the discontinuities (i.e. 90deg, 270 deg, etc) */ + if IS_EQ(fmod((arg - M_PI_2), M_PI), 0.0) { + if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0) + *cvalue = 0.0f; /* no value possible here */ + } + else + fn= tan; + } + break; + case FCM_GENERATOR_FN_LN: /* natural log */ + { + /* check that value is greater than 1? */ + if (arg > 1.0f) { + fn= log; + } + else { + if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0) + *cvalue = 0.0f; /* no value possible here */ + } + } + break; + case FCM_GENERATOR_FN_SQRT: /* square root */ + { + /* no negative numbers */ + if (arg > 0.0f) { + fn= sqrt; + } + else { + if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0) + *cvalue = 0.0f; /* no value possible here */ + } + } + break; + + default: + printf("Invalid Function-Generator for F-Modifier - %d \n", data->type); + } + + /* execute function callback to set value if appropriate */ + if (fn) { + float value= (float)(data->amplitude*fn(arg) + data->value_offset); + + if (data->flag & FCM_GENERATOR_ADDITIVE) + *cvalue += value; + else + *cvalue= value; + } +} + +static FModifierTypeInfo FMI_FN_GENERATOR = { + FMODIFIER_TYPE_FN_GENERATOR, /* type */ + sizeof(FMod_FunctionGenerator), /* size */ + FMI_TYPE_GENERATE_CURVE, /* action type */ + FMI_REQUIRES_NOTHING, /* requirements */ + "Built-In Function", /* name */ + "FMod_FunctionGenerator", /* struct name */ + NULL, /* free data */ + NULL, /* copy data */ + fcm_fn_generator_new_data, /* new data */ + NULL, /* verify */ + NULL, /* evaluate time */ + fcm_fn_generator_evaluate /* evaluate */ +}; + +/* Envelope F-Curve Modifier --------------------------- */ + +static void fcm_envelope_free (FModifier *fcm) +{ + FMod_Envelope *env= (FMod_Envelope *)fcm->data; + + /* free envelope data array */ + if (env->data) + MEM_freeN(env->data); +} + +static void fcm_envelope_copy (FModifier *fcm, FModifier *src) +{ + FMod_Envelope *env= (FMod_Envelope *)fcm->data; + FMod_Envelope *oenv= (FMod_Envelope *)src->data; + + /* copy envelope data array */ + if (oenv->data) + env->data= MEM_dupallocN(oenv->data); +} + +static void fcm_envelope_new_data (void *mdata) +{ + FMod_Envelope *env= (FMod_Envelope *)mdata; + + /* set default min/max ranges */ + env->min= -1.0f; + env->max= 1.0f; +} + +static void fcm_envelope_verify (FModifier *fcm) +{ + FMod_Envelope *env= (FMod_Envelope *)fcm->data; + + /* if the are points, perform bubble-sort on them, as user may have changed the order */ + if (env->data) { + // XXX todo... + } +} + +static void fcm_envelope_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) +{ + FMod_Envelope *env= (FMod_Envelope *)fcm->data; + FCM_EnvelopeData *fed, *prevfed, *lastfed; + float min=0.0f, max=0.0f, fac=0.0f; + int a; + + /* get pointers */ + if (env->data == NULL) return; + prevfed= env->data; + fed= prevfed + 1; + lastfed= prevfed + (env->totvert-1); + + /* get min/max values for envelope at evaluation time (relative to mid-value) */ + if (prevfed->time >= evaltime) { + /* before or on first sample, so just extend value */ + min= prevfed->min; + max= prevfed->max; + } + else if (lastfed->time <= evaltime) { + /* after or on last sample, so just extend value */ + min= lastfed->min; + max= lastfed->max; + } + else { + /* evaltime occurs somewhere between segments */ + // TODO: implement binary search for this to make it faster? + for (a=0; prevfed && fed && (a < env->totvert-1); a++, prevfed=fed, fed++) { + /* evaltime occurs within the interval defined by these two envelope points */ + if ((prevfed->time <= evaltime) && (fed->time >= evaltime)) { + float afac, bfac, diff; + + diff= fed->time - prevfed->time; + afac= (evaltime - prevfed->time) / diff; + bfac= (fed->time - evaltime) / diff; + + min= bfac*prevfed->min + afac*fed->min; + max= bfac*prevfed->max + afac*fed->max; + + break; + } + } + } + + /* adjust *cvalue + * - fac is the ratio of how the current y-value corresponds to the reference range + * - thus, the new value is found by mapping the old range to the new! + */ + fac= (*cvalue - (env->midval + env->min)) / (env->max - env->min); + *cvalue= min + fac*(max - min); +} + +static FModifierTypeInfo FMI_ENVELOPE = { + FMODIFIER_TYPE_ENVELOPE, /* type */ + sizeof(FMod_Envelope), /* size */ + FMI_TYPE_REPLACE_VALUES, /* action type */ + 0, /* requirements */ + "Envelope", /* name */ + "FMod_Envelope", /* struct name */ + fcm_envelope_free, /* free data */ + fcm_envelope_copy, /* copy data */ + fcm_envelope_new_data, /* new data */ + fcm_envelope_verify, /* verify */ + NULL, /* evaluate time */ + fcm_envelope_evaluate /* evaluate */ +}; + +/* Cycles F-Curve Modifier --------------------------- */ + +/* This modifier changes evaltime to something that exists within the curve's frame-range, + * then re-evaluates modifier stack up to this point using the new time. This re-entrant behaviour + * is very likely to be more time-consuming than the original approach... (which was tighly integrated into + * the calculation code...). + * + * NOTE: this needs to be at the start of the stack to be of use, as it needs to know the extents of the keyframes/sample-data + * Possible TODO - store length of cycle information that can be initialised from the extents of the keyframes/sample-data, and adjusted + * as appropriate + */ + +/* temp data used during evaluation */ +typedef struct tFCMED_Cycles { + float cycyofs; /* y-offset to apply */ +} tFCMED_Cycles; + +static void fcm_cycles_new_data (void *mdata) +{ + FMod_Cycles *data= (FMod_Cycles *)mdata; + + /* turn on cycles by default */ + data->before_mode= data->after_mode= FCM_EXTRAPOLATE_CYCLIC; +} + +static float fcm_cycles_time (FCurve *fcu, FModifier *fcm, float cvalue, float evaltime) +{ + FMod_Cycles *data= (FMod_Cycles *)fcm->data; + float prevkey[2], lastkey[2], cycyofs=0.0f; + short side=0, mode=0; + int cycles=0; + + /* check if modifier is first in stack, otherwise disable ourself... */ + // FIXME... + if (fcm->prev) { + fcm->flag |= FMODIFIER_FLAG_DISABLED; + return evaltime; + } + + /* calculate new evaltime due to cyclic interpolation */ + if (fcu && fcu->bezt) { + BezTriple *prevbezt= fcu->bezt; + BezTriple *lastbezt= prevbezt + fcu->totvert-1; + + prevkey[0]= prevbezt->vec[1][0]; + prevkey[1]= prevbezt->vec[1][1]; + + lastkey[0]= lastbezt->vec[1][0]; + lastkey[1]= lastbezt->vec[1][1]; + } + else if (fcu && fcu->fpt) { + FPoint *prevfpt= fcu->fpt; + FPoint *lastfpt= prevfpt + fcu->totvert-1; + + prevkey[0]= prevfpt->vec[0]; + prevkey[1]= prevfpt->vec[1]; + + lastkey[0]= lastfpt->vec[0]; + lastkey[1]= lastfpt->vec[1]; + } + else + return evaltime; + + /* check if modifier will do anything + * 1) if in data range, definitely don't do anything + * 2) if before first frame or after last frame, make sure some cycling is in use + */ + if (evaltime < prevkey[0]) { + if (data->before_mode) { + side= -1; + mode= data->before_mode; + cycles= data->before_cycles; + } + } + else if (evaltime > lastkey[0]) { + if (data->after_mode) { + side= 1; + mode= data->after_mode; + cycles= data->after_cycles; + } + } + if ELEM(0, side, mode) + return evaltime; + + /* find relative place within a cycle */ + { + float cycdx=0, cycdy=0, ofs=0; + float cycle= 0; + + /* ofs is start frame of cycle */ + ofs= prevkey[0]; + + /* calculate period and amplitude (total height) of a cycle */ + cycdx= lastkey[0] - prevkey[0]; + cycdy= lastkey[1] - prevkey[1]; + + /* check if cycle is infinitely small, to be point of being impossible to use */ + if (cycdx == 0) + return evaltime; + + /* calculate the 'number' of the cycle */ + cycle= ((float)side * (evaltime - ofs) / cycdx); + + /* check that cyclic is still enabled for the specified time */ + if (cycles == 0) { + /* catch this case so that we don't exit when we have cycles=0 + * as this indicates infinite cycles... + */ + } + else if (cycle > (cycles+1)) { + /* we are too far away from range to evaluate + * TODO: but we should still hold last value... + */ + return evaltime; + } + + /* check if 'cyclic extrapolation', and thus calculate y-offset for this cycle */ + if (mode == FCM_EXTRAPOLATE_CYCLIC_OFFSET) { + cycyofs = (float)floor((evaltime - ofs) / cycdx); + cycyofs *= cycdy; + } + + /* calculate where in the cycle we are (overwrite evaltime to reflect this) */ + if ((mode == FCM_EXTRAPOLATE_MIRROR) && ((int)(cycle) % 2)) { + /* when 'mirror' option is used and cycle number is odd, this cycle is played in reverse + * - for 'before' extrapolation, we need to flip in a different way, otherwise values past + * then end of the curve get referenced (result of fmod will be negative, and with different phase) + */ + if (side < 0) + evaltime= (float)(prevkey[0] - fmod(evaltime-ofs, cycdx)); + else + evaltime= (float)(lastkey[0] - fmod(evaltime-ofs, cycdx)); + } + else { + /* the cycle is played normally... */ + evaltime= (float)(fmod(evaltime-ofs, cycdx) + ofs); + } + if (evaltime < ofs) evaltime += cycdx; + } + + /* store temp data if needed */ + if (mode == FCM_EXTRAPOLATE_CYCLIC_OFFSET) { + tFCMED_Cycles *edata; + + /* for now, this is just a float, but we could get more stuff... */ + fcm->edata= edata= MEM_callocN(sizeof(tFCMED_Cycles), "tFCMED_Cycles"); + edata->cycyofs= cycyofs; + } + + /* return the new frame to evaluate */ + return evaltime; +} + +static void fcm_cycles_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) +{ + tFCMED_Cycles *edata= (tFCMED_Cycles *)fcm->edata; + + /* use temp data */ + if (edata) { + /* add cyclic offset - no need to check for now, otherwise the data wouldn't exist! */ + *cvalue += edata->cycyofs; + + /* free temp data */ + MEM_freeN(edata); + fcm->edata= NULL; + } +} + +static FModifierTypeInfo FMI_CYCLES = { + FMODIFIER_TYPE_CYCLES, /* type */ + sizeof(FMod_Cycles), /* size */ + FMI_TYPE_EXTRAPOLATION, /* action type */ + FMI_REQUIRES_ORIGINAL_DATA, /* requirements */ + "Cycles", /* name */ + "FMod_Cycles", /* struct name */ + NULL, /* free data */ + NULL, /* copy data */ + fcm_cycles_new_data, /* new data */ + NULL /*fcm_cycles_verify*/, /* verify */ + fcm_cycles_time, /* evaluate time */ + fcm_cycles_evaluate /* evaluate */ +}; + +/* Noise F-Curve Modifier --------------------------- */ + +static void fcm_noise_new_data (void *mdata) +{ + FMod_Noise *data= (FMod_Noise *)mdata; + + /* defaults */ + data->size= 1.0f; + data->strength= 1.0f; + data->phase= 1.0f; + data->depth = 0; + data->modification = FCM_NOISE_MODIF_REPLACE; +} + +static void fcm_noise_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) +{ + FMod_Noise *data= (FMod_Noise *)fcm->data; + float noise; + + noise = BLI_turbulence(data->size, evaltime, data->phase, 0.f, data->depth); + + switch (data->modification) { + case FCM_NOISE_MODIF_ADD: + *cvalue= *cvalue + noise * data->strength; + break; + case FCM_NOISE_MODIF_SUBTRACT: + *cvalue= *cvalue - noise * data->strength; + break; + case FCM_NOISE_MODIF_MULTIPLY: + *cvalue= *cvalue * noise * data->strength; + break; + case FCM_NOISE_MODIF_REPLACE: + default: + *cvalue= *cvalue + (noise - 0.5f) * data->strength; + break; + } +} + +static FModifierTypeInfo FMI_NOISE = { + FMODIFIER_TYPE_NOISE, /* type */ + sizeof(FMod_Noise), /* size */ + FMI_TYPE_REPLACE_VALUES, /* action type */ + 0, /* requirements */ + "Noise", /* name */ + "FMod_Noise", /* struct name */ + NULL, /* free data */ + NULL, /* copy data */ + fcm_noise_new_data, /* new data */ + NULL /*fcm_noise_verify*/, /* verify */ + NULL, /* evaluate time */ + fcm_noise_evaluate /* evaluate */ +}; + +/* Filter F-Curve Modifier --------------------------- */ + +#if 0 // XXX not yet implemented +static FModifierTypeInfo FMI_FILTER = { + FMODIFIER_TYPE_FILTER, /* type */ + sizeof(FMod_Filter), /* size */ + FMI_TYPE_REPLACE_VALUES, /* action type */ + 0, /* requirements */ + "Filter", /* name */ + "FMod_Filter", /* struct name */ + NULL, /* free data */ + NULL, /* copy data */ + NULL, /* new data */ + NULL /*fcm_filter_verify*/, /* verify */ + NULL, /* evlauate time */ + fcm_filter_evaluate /* evaluate */ +}; +#endif // XXX not yet implemented + + +/* Python F-Curve Modifier --------------------------- */ + +static void fcm_python_free (FModifier *fcm) +{ + FMod_Python *data= (FMod_Python *)fcm->data; + + /* id-properties */ + IDP_FreeProperty(data->prop); + MEM_freeN(data->prop); +} + +static void fcm_python_new_data (void *mdata) +{ + FMod_Python *data= (FMod_Python *)mdata; + + /* everything should be set correctly by calloc, except for the prop->type constant.*/ + data->prop = MEM_callocN(sizeof(IDProperty), "PyFModifierProps"); + data->prop->type = IDP_GROUP; +} + +static void fcm_python_copy (FModifier *fcm, FModifier *src) +{ + FMod_Python *pymod = (FMod_Python *)fcm->data; + FMod_Python *opymod = (FMod_Python *)src->data; + + pymod->prop = IDP_CopyProperty(opymod->prop); +} + +static void fcm_python_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) +{ +#ifndef DISABLE_PYTHON + //FMod_Python *data= (FMod_Python *)fcm->data; + + /* FIXME... need to implement this modifier... + * It will need it execute a script using the custom properties + */ +#endif /* DISABLE_PYTHON */ +} + +static FModifierTypeInfo FMI_PYTHON = { + FMODIFIER_TYPE_PYTHON, /* type */ + sizeof(FMod_Python), /* size */ + FMI_TYPE_GENERATE_CURVE, /* action type */ + FMI_REQUIRES_RUNTIME_CHECK, /* requirements */ + "Python", /* name */ + "FMod_Python", /* struct name */ + fcm_python_free, /* free data */ + fcm_python_copy, /* copy data */ + fcm_python_new_data, /* new data */ + NULL /*fcm_python_verify*/, /* verify */ + NULL /*fcm_python_time*/, /* evaluate time */ + fcm_python_evaluate /* evaluate */ +}; + + +/* Limits F-Curve Modifier --------------------------- */ + +static float fcm_limits_time (FCurve *fcu, FModifier *fcm, float cvalue, float evaltime) +{ + FMod_Limits *data= (FMod_Limits *)fcm->data; + + /* check for the time limits */ + if ((data->flag & FCM_LIMIT_XMIN) && (evaltime < data->rect.xmin)) + return data->rect.xmin; + if ((data->flag & FCM_LIMIT_XMAX) && (evaltime > data->rect.xmax)) + return data->rect.xmax; + + /* modifier doesn't change time */ + return evaltime; +} + +static void fcm_limits_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) +{ + FMod_Limits *data= (FMod_Limits *)fcm->data; + + /* value limits now */ + if ((data->flag & FCM_LIMIT_YMIN) && (*cvalue < data->rect.ymin)) + *cvalue= data->rect.ymin; + if ((data->flag & FCM_LIMIT_YMAX) && (*cvalue > data->rect.ymax)) + *cvalue= data->rect.ymax; +} + +static FModifierTypeInfo FMI_LIMITS = { + FMODIFIER_TYPE_LIMITS, /* type */ + sizeof(FMod_Limits), /* size */ + FMI_TYPE_GENERATE_CURVE, /* action type */ /* XXX... err... */ + FMI_REQUIRES_RUNTIME_CHECK, /* requirements */ + "Limits", /* name */ + "FMod_Limits", /* struct name */ + NULL, /* free data */ + NULL, /* copy data */ + NULL, /* new data */ + NULL, /* verify */ + fcm_limits_time, /* evaluate time */ + fcm_limits_evaluate /* evaluate */ +}; + +/* F-Curve Modifier API --------------------------- */ +/* All of the F-Curve Modifier api functions use FModifierTypeInfo structs to carry out + * and operations that involve F-Curve modifier specific code. + */ + +/* These globals only ever get directly accessed in this file */ +static FModifierTypeInfo *fmodifiersTypeInfo[FMODIFIER_NUM_TYPES]; +static short FMI_INIT= 1; /* when non-zero, the list needs to be updated */ + +/* This function only gets called when FMI_INIT is non-zero */ +static void fmods_init_typeinfo () +{ + fmodifiersTypeInfo[0]= NULL; /* 'Null' F-Curve Modifier */ + fmodifiersTypeInfo[1]= &FMI_GENERATOR; /* Generator F-Curve Modifier */ + fmodifiersTypeInfo[2]= &FMI_FN_GENERATOR; /* Built-In Function Generator F-Curve Modifier */ + fmodifiersTypeInfo[3]= &FMI_ENVELOPE; /* Envelope F-Curve Modifier */ + fmodifiersTypeInfo[4]= &FMI_CYCLES; /* Cycles F-Curve Modifier */ + fmodifiersTypeInfo[5]= &FMI_NOISE; /* Apply-Noise F-Curve Modifier */ + fmodifiersTypeInfo[6]= NULL/*&FMI_FILTER*/; /* Filter F-Curve Modifier */ // XXX unimplemented + fmodifiersTypeInfo[7]= &FMI_PYTHON; /* Custom Python F-Curve Modifier */ + fmodifiersTypeInfo[8]= &FMI_LIMITS; /* Limits F-Curve Modifier */ +} + +/* This function should be used for getting the appropriate type-info when only + * a F-Curve modifier type is known + */ +FModifierTypeInfo *get_fmodifier_typeinfo (int type) +{ + /* initialise the type-info list? */ + if (FMI_INIT) { + fmods_init_typeinfo(); + FMI_INIT = 0; + } + + /* only return for valid types */ + if ( (type >= FMODIFIER_TYPE_NULL) && + (type <= FMODIFIER_NUM_TYPES ) ) + { + /* there shouldn't be any segfaults here... */ + return fmodifiersTypeInfo[type]; + } + else { + printf("No valid F-Curve Modifier type-info data available. Type = %i \n", type); + } + + return NULL; +} + +/* This function should always be used to get the appropriate type-info, as it + * has checks which prevent segfaults in some weird cases. + */ +FModifierTypeInfo *fmodifier_get_typeinfo (FModifier *fcm) +{ + /* only return typeinfo for valid modifiers */ + if (fcm) + return get_fmodifier_typeinfo(fcm->type); + else + return NULL; +} + +/* API --------------------------- */ + +/* Add a new F-Curve Modifier to the given F-Curve of a certain type */ +FModifier *add_fmodifier (ListBase *modifiers, int type) +{ + FModifierTypeInfo *fmi= get_fmodifier_typeinfo(type); + FModifier *fcm; + + /* sanity checks */ + if ELEM(NULL, modifiers, fmi) + return NULL; + + /* special checks for whether modifier can be added */ + if ((modifiers->first) && (type == FMODIFIER_TYPE_CYCLES)) { + /* cycles modifier must be first in stack, so for now, don't add if it can't be */ + // TODO: perhaps there is some better way, but for now, + printf("Error: Cannot add 'Cycles' modifier to F-Curve, as 'Cycles' modifier can only be first in stack. \n"); + return NULL; + } + + /* add modifier itself */ + fcm= MEM_callocN(sizeof(FModifier), "F-Curve Modifier"); + fcm->type = type; + fcm->flag = FMODIFIER_FLAG_EXPANDED; + BLI_addtail(modifiers, fcm); + + /* add modifier's data */ + fcm->data= MEM_callocN(fmi->size, fmi->structName); + + /* init custom settings if necessary */ + if (fmi->new_data) + fmi->new_data(fcm->data); + + /* return modifier for further editing */ + return fcm; +} + +/* Duplicate all of the F-Modifiers in the Modifier stacks */ +void copy_fmodifiers (ListBase *dst, ListBase *src) +{ + FModifier *fcm, *srcfcm; + + if ELEM(NULL, dst, src) + return; + + dst->first= dst->last= NULL; + BLI_duplicatelist(dst, src); + + for (fcm=dst->first, srcfcm=src->first; fcm && srcfcm; srcfcm=srcfcm->next, fcm=fcm->next) { + FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); + + /* make a new copy of the F-Modifier's data */ + fcm->data = MEM_dupallocN(fcm->data); + + /* only do specific constraints if required */ + if (fmi && fmi->copy_data) + fmi->copy_data(fcm, srcfcm); + } +} + +/* Remove and free the given F-Modifier from the given stack */ +void remove_fmodifier (ListBase *modifiers, FModifier *fcm) +{ + FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); + + /* sanity check */ + if (fcm == NULL) + return; + + /* free modifier's special data (stored inside fcm->data) */ + if (fcm->data) { + if (fmi && fmi->free_data) + fmi->free_data(fcm); + + /* free modifier's data (fcm->data) */ + MEM_freeN(fcm->data); + } + + /* remove modifier from stack */ + if (modifiers) + BLI_freelinkN(modifiers, fcm); + else { + // XXX this case can probably be removed some day, as it shouldn't happen... + printf("remove_fmodifier() - no modifier stack given \n"); + MEM_freeN(fcm); + } +} + +/* Remove all of a given F-Curve's modifiers */ +void free_fmodifiers (ListBase *modifiers) +{ + FModifier *fcm, *fmn; + + /* sanity check */ + if (modifiers == NULL) + return; + + /* free each modifier in order - modifier is unlinked from list and freed */ + for (fcm= modifiers->first; fcm; fcm= fmn) { + fmn= fcm->next; + remove_fmodifier(modifiers, fcm); + } +} + +/* Find the active F-Modifier */ +FModifier *find_active_fmodifier (ListBase *modifiers) +{ + FModifier *fcm; + + /* sanity checks */ + if ELEM(NULL, modifiers, modifiers->first) + return NULL; + + /* loop over modifiers until 'active' one is found */ + for (fcm= modifiers->first; fcm; fcm= fcm->next) { + if (fcm->flag & FMODIFIER_FLAG_ACTIVE) + return fcm; + } + + /* no modifier is active */ + return NULL; +} + +/* Set the active F-Modifier */ +void set_active_fmodifier (ListBase *modifiers, FModifier *fcm) +{ + FModifier *fm; + + /* sanity checks */ + if ELEM(NULL, modifiers, modifiers->first) + return; + + /* deactivate all, and set current one active */ + for (fm= modifiers->first; fm; fm= fm->next) + fm->flag &= ~FMODIFIER_FLAG_ACTIVE; + + /* make given modifier active */ + if (fcm) + fcm->flag |= FMODIFIER_FLAG_ACTIVE; +} + +/* Do we have any modifiers which match certain criteria + * - mtype - type of modifier (if 0, doesn't matter) + * - acttype - type of action to perform (if -1, doesn't matter) + */ +short list_has_suitable_fmodifier (ListBase *modifiers, int mtype, short acttype) +{ + FModifier *fcm; + + /* if there are no specific filtering criteria, just skip */ + if ((mtype == 0) && (acttype == 0)) + return (modifiers && modifiers->first); + + /* sanity checks */ + if ELEM(NULL, modifiers, modifiers->first) + return 0; + + /* find the first mdifier fitting these criteria */ + for (fcm= modifiers->first; fcm; fcm= fcm->next) { + FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); + short mOk=1, aOk=1; /* by default 1, so that when only one test, won't fail */ + + /* check if applicable ones are fullfilled */ + if (mtype) + mOk= (fcm->type == mtype); + if (acttype > -1) + aOk= (fmi->acttype == acttype); + + /* if both are ok, we've found a hit */ + if (mOk && aOk) + return 1; + } + + /* no matches */ + return 0; +} + +/* Evaluation API --------------------------- */ + +/* evaluate time modifications imposed by some F-Curve Modifiers + * - this step acts as an optimisation to prevent the F-Curve stack being evaluated + * several times by modifiers requesting the time be modified, as the final result + * would have required using the modified time + * - modifiers only ever recieve the unmodified time, as subsequent modifiers should be + * working on the 'global' result of the modified curve, not some localised segment, + * so nevaltime gets set to whatever the last time-modifying modifier likes... + * - we start from the end of the stack, as only the last one matters for now + */ +float evaluate_time_fmodifiers (ListBase *modifiers, FCurve *fcu, float cvalue, float evaltime) +{ + FModifier *fcm; + float m_evaltime= evaltime; + + /* sanity checks */ + if ELEM(NULL, modifiers, modifiers->last) + return evaltime; + + /* find the first modifier from end of stack that modifies time, and calculate the time the modifier + * would calculate time at + */ + for (fcm= modifiers->last; fcm; fcm= fcm->prev) { + FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); + + /* only evaluate if there's a callback for this */ + // TODO: implement the 'influence' control feature... + if (fmi && fmi->evaluate_modifier_time) { + if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0) + m_evaltime= fmi->evaluate_modifier_time(fcu, fcm, cvalue, evaltime); + break; + } + } + + /* return the modified evaltime */ + return m_evaltime; +} + +/* Evalautes the given set of F-Curve Modifiers using the given data + * Should only be called after evaluate_time_fmodifiers() has been called... + */ +void evaluate_value_fmodifiers (ListBase *modifiers, FCurve *fcu, float *cvalue, float evaltime) +{ + FModifier *fcm; + + /* sanity checks */ + if ELEM(NULL, modifiers, modifiers->first) + return; + + /* evaluate modifiers */ + for (fcm= modifiers->first; fcm; fcm= fcm->next) { + FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); + + /* only evaluate if there's a callback for this */ + // TODO: implement the 'influence' control feature... + if (fmi && fmi->evaluate_modifier) { + if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0) + fmi->evaluate_modifier(fcu, fcm, cvalue, evaltime); + } + } +} + +/* ---------- */ + +/* Bake modifiers for given F-Curve to curve sample data, in the frame range defined + * by start and end (inclusive). + */ +void fcurve_bake_modifiers (FCurve *fcu, int start, int end) +{ + ChannelDriver *driver; + + /* sanity checks */ + // TODO: make these tests report errors using reports not printf's + if ELEM(NULL, fcu, fcu->modifiers.first) { + printf("Error: No F-Curve with F-Curve Modifiers to Bake\n"); + return; + } + + /* temporarily, disable driver while we sample, so that they don't influence the outcome */ + driver= fcu->driver; + fcu->driver= NULL; + + /* bake the modifiers, by sampling the curve at each frame */ + fcurve_store_samples(fcu, NULL, start, end, fcurve_samplingcb_evalcurve); + + /* free the modifiers now */ + free_fmodifiers(&fcu->modifiers); + + /* restore driver */ + fcu->driver= driver; +} diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index 968a0e68fb9..c3c5483574e 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -1153,7 +1153,7 @@ static void icu_to_fcurves (ListBase *groups, ListBase *list, IpoCurve *icu, cha /* Add a new FModifier (Cyclic) instead of setting extend value * as that's the new equivilant of that option. */ - FModifier *fcm= fcurve_add_modifier(fcu, FMODIFIER_TYPE_CYCLES); + FModifier *fcm= add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_CYCLES); FMod_Cycles *data= (FMod_Cycles *)fcm->data; /* if 'offset' one is in use, set appropriate settings */ diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 2b95584dc25..14e658b3903 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -69,8 +69,6 @@ // TODO: with things like transitions, should these get freed too? Maybe better as a UI tool void free_nlastrip (ListBase *strips, NlaStrip *strip) { - FModifier *fcm, *fmn; - /* sanity checks */ if (strip == NULL) return; @@ -86,13 +84,8 @@ void free_nlastrip (ListBase *strips, NlaStrip *strip) /* free own F-Curves */ free_fcurves(&strip->fcurves); - /* free F-Modifiers */ - for (fcm= strip->modifiers.first; fcm; fcm= fmn) { - fmn= fcm->next; - - BLI_remlink(&strip->modifiers, fcm); - fcurve_remove_modifier(NULL, fcm); - } + /* free own F-Modifiers */ + free_fmodifiers(&strip->modifiers); /* free the strip itself */ if (strips) @@ -167,7 +160,7 @@ NlaStrip *copy_nlastrip (NlaStrip *strip) /* copy F-Curves and modifiers */ copy_fcurves(&strip_d->fcurves, &strip->fcurves); - fcurve_copy_modifiers(&strip_d->modifiers, &strip->modifiers); + copy_fmodifiers(&strip_d->modifiers, &strip->modifiers); /* return the strip */ return strip_d; diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c index 9c401289011..fdce0965ce3 100644 --- a/source/blender/editors/animation/drivers.c +++ b/source/blender/editors/animation/drivers.c @@ -1,5 +1,30 @@ -/* Testing code for 2.5 animation system - * Copyright 2009, Joshua Leung +/** + * $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 + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Joshua Leung (full recode) + * + * ***** END GPL LICENSE BLOCK ***** */ #include @@ -94,7 +119,7 @@ FCurve *verify_driver_fcurve (ID *id, const char rna_path[], const int array_ind fcu->driver= MEM_callocN(sizeof(ChannelDriver), "ChannelDriver"); /* add simple generator modifier for driver so that there is some visible representation */ - fcurve_add_modifier(fcu, FMODIFIER_TYPE_GENERATOR); + add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR); /* just add F-Curve to end of driver list */ BLI_addtail(&adt->drivers, fcu); diff --git a/source/blender/editors/animation/fmodifier_ui.c b/source/blender/editors/animation/fmodifier_ui.c index 5968817a9a6..b5a99877247 100644 --- a/source/blender/editors/animation/fmodifier_ui.c +++ b/source/blender/editors/animation/fmodifier_ui.c @@ -112,23 +112,23 @@ static void validate_fmodifier_cb (bContext *C, void *fcm_v, void *dummy) } /* callback to set the active modifier */ -static void activate_fmodifier_cb (bContext *C, void *fcu_v, void *fcm_v) +static void activate_fmodifier_cb (bContext *C, void *fmods_v, void *fcm_v) { - FCurve *fcu= (FCurve *)fcu_v; + ListBase *modifiers = (ListBase *)fmods_v; FModifier *fcm= (FModifier *)fcm_v; - /* call API function to set the active modifier for active F-Curve */ - fcurve_set_active_modifier(fcu, fcm); + /* call API function to set the active modifier for active modifier-stack */ + set_active_fmodifier(modifiers, fcm); } /* callback to remove the given modifier */ -static void delete_fmodifier_cb (bContext *C, void *fcu_v, void *fcm_v) +static void delete_fmodifier_cb (bContext *C, void *fmods_v, void *fcm_v) { - FCurve *fcu= (FCurve *)fcu_v; + ListBase *modifiers = (ListBase *)fmods_v; FModifier *fcm= (FModifier *)fcm_v; - /* remove the given F-Modifier from the F-Curve */ - fcurve_remove_modifier(fcu, fcm); + /* remove the given F-Modifier from the active modifier-stack */ + remove_fmodifier(modifiers, fcm); } /* --------------- */ @@ -588,6 +588,7 @@ static void draw_modifier__limits(uiBlock *block, FModifier *fcm, int *yco, shor void ANIM_uiTemplate_fmodifier_draw (uiBlock *block, FCurve *fcu, FModifier *fcm, int *yco) { FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); + ListBase *modifiers= &fcu->modifiers; // XXX fixme... should be arg uiBut *but; short active= (fcm->flag & FMODIFIER_FLAG_ACTIVE); short width= 314; @@ -607,7 +608,7 @@ void ANIM_uiTemplate_fmodifier_draw (uiBlock *block, FCurve *fcu, FModifier *fcm /* checkbox for 'active' status (for now) */ but= uiDefIconButBitS(block, ICONTOG, FMODIFIER_FLAG_ACTIVE, B_REDR, ICON_RADIOBUT_OFF, 25, *yco-1, 20, 20, &fcm->flag, 0.0, 0.0, 0, 0, "Modifier is active one."); - uiButSetFunc(but, activate_fmodifier_cb, fcu, fcm); + uiButSetFunc(but, activate_fmodifier_cb, modifiers, fcm); /* name */ if (fmi) @@ -620,7 +621,7 @@ void ANIM_uiTemplate_fmodifier_draw (uiBlock *block, FCurve *fcu, FModifier *fcm /* delete button */ but= uiDefIconBut(block, BUT, B_REDR, ICON_X, 10+(width-30), *yco, 19, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Delete F-Curve Modifier."); - uiButSetFunc(but, delete_fmodifier_cb, fcu, fcm); + uiButSetFunc(but, delete_fmodifier_cb, modifiers, fcm); uiBlockSetEmboss(block, UI_EMBOSS); } diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index 90804052370..331e2d0894e 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -1,5 +1,30 @@ -/* Testing code for 2.5 animation system - * Copyright 2009, Joshua Leung +/** + * $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 + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Joshua Leung (full recode) + * + * ***** END GPL LICENSE BLOCK ***** */ #include diff --git a/source/blender/editors/animation/keyingsets.c b/source/blender/editors/animation/keyingsets.c index 1813c76d0c4..240089d26a6 100644 --- a/source/blender/editors/animation/keyingsets.c +++ b/source/blender/editors/animation/keyingsets.c @@ -1,5 +1,30 @@ -/* Testing code for 2.5 animation system - * Copyright 2009, Joshua Leung +/** + * $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 + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Joshua Leung (full recode) + * + * ***** END GPL LICENSE BLOCK ***** */ #include diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c index 66168f2ed87..0d7dafe2938 100644 --- a/source/blender/editors/space_graph/graph_draw.c +++ b/source/blender/editors/space_graph/graph_draw.c @@ -795,7 +795,7 @@ void graph_draw_curves (bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGri */ for (ale=anim_data.first; ale; ale=ale->next) { FCurve *fcu= (FCurve *)ale->key_data; - FModifier *fcm= fcurve_find_active_modifier(fcu); + FModifier *fcm= find_active_fmodifier(&fcu->modifiers); AnimData *adt= ANIM_nla_mapping_get(ac, ale); /* map keyframes for drawing if scaled F-Curve */ diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index ca47e69cc75..a82699ac1e5 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -1769,9 +1769,9 @@ static int graph_fmodifier_add_exec(bContext *C, wmOperator *op) type= RNA_enum_get(op->ptr, "type"); /* add F-Modifier of specified type to active F-Curve, and make it the active one */ - fcm= fcurve_add_modifier(fcu, type); + fcm= add_fmodifier(&fcu->modifiers, type); if (fcm) - fcurve_set_active_modifier(fcu, 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; diff --git a/source/blender/editors/space_graph/graph_utils.c b/source/blender/editors/space_graph/graph_utils.c index b1ec795a089..f00e7845549 100644 --- a/source/blender/editors/space_graph/graph_utils.c +++ b/source/blender/editors/space_graph/graph_utils.c @@ -194,7 +194,7 @@ int graphop_visible_keyframes_poll (bContext *C) */ if (fcu->bezt == NULL) continue; - fcm= fcurve_find_active_modifier(fcu); + fcm= find_active_fmodifier(&fcu->modifiers); found= (fcurve_needs_draw_fmodifier_controls(fcu, fcm) == 0); if (found) break; @@ -244,7 +244,7 @@ int graphop_editable_keyframes_poll (bContext *C) */ if (fcu->bezt == NULL) continue; - fcm= fcurve_find_active_modifier(fcu); + fcm= find_active_fmodifier(&fcu->modifiers); found= (fcurve_needs_draw_fmodifier_controls(fcu, fcm) == 0); if (found) break; From 6b784a80f02deaca05e347dc2626dc92826f0944 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 2 Jul 2009 06:41:10 +0000 Subject: [PATCH 079/114] NLA SoC: F-Modifiers working on NLA Strips * Using the Ctrl-Shift-M hotkey, F-Modifiers can be added to all the selected strips. * F-Modifiers can also be added/tweaked from the NLA N-Key properties. The UI now uses the same code as for the graph editor ones. The UI drawing here is currently messed up from the NLA side, since it seems combining normal layout stuff and old-style uiBlocks doesn't seem to work too well (BUT! the buttons are at least functional). Next up, I'll need to recode the buttons panel for the Graph Editor so that all of the drawing can be migrated over to use the new layout engine. --- .../blender/editors/animation/fmodifier_ui.c | 3 +- source/blender/editors/include/ED_anim_api.h | 4 +- .../editors/space_graph/graph_buttons.c | 2 +- .../blender/editors/space_graph/graph_edit.c | 2 +- .../blender/editors/space_graph/graph_ops.c | 3 +- .../blender/editors/space_nla/nla_buttons.c | 16 +++- source/blender/editors/space_nla/nla_edit.c | 81 +++++++++++++++++++ source/blender/editors/space_nla/nla_intern.h | 2 + source/blender/editors/space_nla/nla_ops.c | 5 ++ 9 files changed, 107 insertions(+), 11 deletions(-) diff --git a/source/blender/editors/animation/fmodifier_ui.c b/source/blender/editors/animation/fmodifier_ui.c index b5a99877247..dfac380f595 100644 --- a/source/blender/editors/animation/fmodifier_ui.c +++ b/source/blender/editors/animation/fmodifier_ui.c @@ -585,10 +585,9 @@ static void draw_modifier__limits(uiBlock *block, FModifier *fcm, int *yco, shor /* --------------- */ // FIXME: remove dependency for F-Curve -void ANIM_uiTemplate_fmodifier_draw (uiBlock *block, FCurve *fcu, FModifier *fcm, int *yco) +void ANIM_uiTemplate_fmodifier_draw (uiBlock *block, ListBase *modifiers, FModifier *fcm, int *yco) { FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); - ListBase *modifiers= &fcu->modifiers; // XXX fixme... should be arg uiBut *but; short active= (fcm->flag & FMODIFIER_FLAG_ACTIVE); short width= 314; diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index 4d75a73a327..87f05c8a76a 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -41,7 +41,7 @@ struct gla2DDrawInfo; struct Object; struct bActionGroup; struct FCurve; -struct IpoCurve; // xxx +struct FModifier; /* ************************************************ */ /* ANIMATION CHANNEL FILTERING */ @@ -300,7 +300,7 @@ struct uiBlock; /* draw a given F-Modifier for some layout/UI-Block */ // XXX not quite complete yet -void ANIM_uiTemplate_fmodifier_draw(struct uiBlock *block, struct FCurve *fcu, struct FModifier *fcm, int *yco); +void ANIM_uiTemplate_fmodifier_draw(struct uiBlock *block, ListBase *modifiers, struct FModifier *fcm, int *yco); /* ************************************************* */ /* ASSORTED TOOLS */ diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c index 9d4a1a8b3cb..5616ffc8002 100644 --- a/source/blender/editors/space_graph/graph_buttons.c +++ b/source/blender/editors/space_graph/graph_buttons.c @@ -381,7 +381,7 @@ static void graph_panel_modifiers(const bContext *C, Panel *pa) /* draw each modifier */ for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next) - ANIM_uiTemplate_fmodifier_draw(block, fcu, fcm, &yco); + ANIM_uiTemplate_fmodifier_draw(block, &fcu->modifiers, fcm, &yco); MEM_freeN(ale); } diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index a82699ac1e5..9a50c5cc203 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -1741,7 +1741,7 @@ void GRAPH_OT_smooth (wmOperatorType *ot) /* ************************************************************************** */ /* F-CURVE MODIFIERS */ -/* ******************** Add F-Curve Modifier Operator *********************** */ +/* ******************** Add F-Modifier Operator *********************** */ static int graph_fmodifier_add_exec(bContext *C, wmOperator *op) { diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c index d5e93dafaf0..38bde61a46c 100644 --- a/source/blender/editors/space_graph/graph_ops.c +++ b/source/blender/editors/space_graph/graph_ops.c @@ -221,8 +221,7 @@ static void graphedit_keymap_keyframes (wmWindowManager *wm, ListBase *keymap) WM_keymap_add_item(keymap, "GRAPH_OT_previewrange_set", PKEY, KM_PRESS, KM_CTRL|KM_ALT, 0); WM_keymap_add_item(keymap, "GRAPH_OT_view_all", HOMEKEY, KM_PRESS, 0, 0); - /* F-Curve Modifiers */ - // XXX these are temporary? operators... + /* F-Modifiers */ WM_keymap_add_item(keymap, "GRAPH_OT_fmodifier_add", MKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0); diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c index 003eba64ed9..1ef72760bfc 100644 --- a/source/blender/editors/space_nla/nla_buttons.c +++ b/source/blender/editors/space_nla/nla_buttons.c @@ -309,18 +309,28 @@ static void nla_panel_evaluation(const bContext *C, Panel *pa) static void nla_panel_modifiers(const bContext *C, Panel *pa) { PointerRNA strip_ptr; + NlaStrip *strip; + FModifier *fcm; uiLayout *layout= pa->layout; - //uiLayout *column, *row, *subcol; uiBlock *block; + int yco = 190; // xxx old /* check context and also validity of pointer */ if (!nla_panel_context(C, NULL, &strip_ptr)) return; + strip= strip_ptr.data; block= uiLayoutGetBlock(layout); uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL); - - // TODO... + + /* 'add modifier' button at top of panel */ + // XXX for now, this will be a operator button which calls a temporary 'add modifier' operator + // FIXME: we need to set the only-active property so that this will only add modifiers for the active strip (not all selected) + uiDefButO(block, BUT, "NLA_OT_fmodifier_add", WM_OP_INVOKE_REGION_WIN, "Add Modifier", 10, 225, 150, 20, "Adds a new F-Modifier for the active NLA Strip"); + + /* draw each modifier */ + for (fcm= strip->modifiers.first; fcm; fcm= fcm->next) + ANIM_uiTemplate_fmodifier_draw(block, &strip->modifiers, fcm, &yco); } /* ******************* general ******************************** */ diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index 6d82e3d4be2..9910e62b262 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -66,6 +66,7 @@ #include "RNA_access.h" #include "RNA_define.h" +#include "RNA_enum_types.h" #include "WM_api.h" #include "WM_types.h" @@ -1021,3 +1022,83 @@ void NLA_OT_clear_scale (wmOperatorType *ot) } /* *********************************************** */ +/* NLA Modifiers */ + +/* ******************** Add F-Modifier Operator *********************** */ + +static int nla_fmodifier_add_exec(bContext *C, wmOperator *op) +{ + bAnimContext ac; + + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + FModifier *fcm; + int type= RNA_enum_get(op->ptr, "type"); + short onlyActive = RNA_boolean_get(op->ptr, "only_active"); + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* get a list of the editable tracks being shown in the NLA */ + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* for each NLA-Track, add the specified modifier to all selected strips */ + for (ale= anim_data.first; ale; ale= ale->next) { + NlaTrack *nlt= (NlaTrack *)ale->data; + NlaStrip *strip; + int i = 1; + + for (strip= nlt->strips.first; strip; strip=strip->next, i++) { + /* only add F-Modifier if on active strip? */ + if ((onlyActive) && (strip->flag & NLASTRIP_FLAG_ACTIVE)==0) + continue; + + /* add F-Modifier of specified type to selected, and make it the active one */ + fcm= add_fmodifier(&strip->modifiers, type); + + if (fcm) + set_active_fmodifier(&strip->modifiers, fcm); + else { + char errormsg[128]; + sprintf(errormsg, "Modifier couldn't be added to (%s : %d). See console for details.", nlt->name, i); + + BKE_report(op->reports, RPT_ERROR, errormsg); + } + } + } + + /* free temp data */ + BLI_freelistN(&anim_data); + + /* set notifier that things have changed */ + ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); + WM_event_add_notifier(C, NC_SCENE, NULL); + + /* done */ + return OPERATOR_FINISHED; +} + +void NLA_OT_fmodifier_add (wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Add F-Modifier"; + ot->idname= "NLA_OT_fmodifier_add"; + + /* api callbacks */ + ot->invoke= WM_menu_invoke; + ot->exec= nla_fmodifier_add_exec; + ot->poll= nlaop_poll_tweakmode_off; + + /* 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", 0, "Only Active", "Only add F-Modifier of the specified type to the active strip."); +} + +/* *********************************************** */ diff --git a/source/blender/editors/space_nla/nla_intern.h b/source/blender/editors/space_nla/nla_intern.h index f8df41d6225..5921b8a75ce 100644 --- a/source/blender/editors/space_nla/nla_intern.h +++ b/source/blender/editors/space_nla/nla_intern.h @@ -105,6 +105,8 @@ void NLA_OT_move_down(wmOperatorType *ot); void NLA_OT_apply_scale(wmOperatorType *ot); void NLA_OT_clear_scale(wmOperatorType *ot); +void NLA_OT_fmodifier_add(wmOperatorType *ot); + /* **************************************** */ /* nla_channels.c */ diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c index d7bd894ce4d..7caab02d6a0 100644 --- a/source/blender/editors/space_nla/nla_ops.c +++ b/source/blender/editors/space_nla/nla_ops.c @@ -155,6 +155,8 @@ void nla_operatortypes(void) WM_operatortype_append(NLA_OT_apply_scale); WM_operatortype_append(NLA_OT_clear_scale); + + WM_operatortype_append(NLA_OT_fmodifier_add); } /* ************************** registration - keymaps **********************************/ @@ -255,6 +257,9 @@ static void nla_keymap_main (wmWindowManager *wm, ListBase *keymap) /* clear scale */ WM_keymap_add_item(keymap, "NLA_OT_clear_scale", SKEY, KM_PRESS, KM_ALT, 0); + /* add f-modifier */ + WM_keymap_add_item(keymap, "NLA_OT_fmodifier_add", MKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0); + /* transform system */ transform_keymap_for_space(wm, keymap, SPACE_NLA); } From 441bcaae2e63d3f757ee336fb051a9cb851e3e33 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 2 Jul 2009 12:41:03 +0000 Subject: [PATCH 080/114] NLA SoC: FModifier drawing converted to use Layout Engine * Most of the F-Modifiers have been ported to use the layout engine + RNA for drawing their buttons now. This plays much nicer with various button-layouts. --> As a nice demo, try adding a Noise Modifier to a NLA-strip, and change the 'size' setting to about 2 to see some effects. * Generator and Envelope modifiers haven't been ported yet since they're quite complex (requiring more time + energy), and as such, have been made to have some temporary error prints instead. Will check on this tomorrow. * Finished/cleaned up the RNA-wrapping of most FModifiers. TODO's (help requested... Brecht?): Generator modifier's UI cannot be wrapped yet using the layout engine (though I might try using the old system only), as I'm having some trouble wrapping the coefficients array for this (see rna_fcurve.c - rna_def_fmodifier_generator()) --- .../blender/editors/animation/fmodifier_ui.c | 275 +++++++++--------- source/blender/editors/include/ED_anim_api.h | 4 +- .../editors/space_graph/graph_buttons.c | 22 +- .../blender/editors/space_nla/nla_buttons.c | 23 +- source/blender/makesrna/RNA_access.h | 1 + source/blender/makesrna/intern/rna_fcurve.c | 111 ++++--- 6 files changed, 231 insertions(+), 205 deletions(-) diff --git a/source/blender/editors/animation/fmodifier_ui.c b/source/blender/editors/animation/fmodifier_ui.c index dfac380f595..19c7d049758 100644 --- a/source/blender/editors/animation/fmodifier_ui.c +++ b/source/blender/editors/animation/fmodifier_ui.c @@ -97,7 +97,7 @@ // XXX for now, roundbox has it's callback func set to NULL to not intercept events #define DRAW_BACKDROP(height) \ { \ - uiDefBut(block, ROUNDBOX, B_REDR, "", -3, *yco-height, width+3, height-1, NULL, 5.0, 0.0, 12.0, (float)rb_col, ""); \ + uiDefBut(block, ROUNDBOX, B_REDR, "", -3, yco-height, width+3, height-1, NULL, 5.0, 0.0, 12.0, (float)rb_col, ""); \ } /* callback to verify modifier data */ @@ -134,26 +134,19 @@ static void delete_fmodifier_cb (bContext *C, void *fmods_v, void *fcm_v) /* --------------- */ /* draw settings for generator modifier */ -static void draw_modifier__generator(uiBlock *block, FModifier *fcm, int *yco, short *height, short width, short active, int rb_col) +static void draw_modifier__generator(uiLayout *layout, FModifier *fcm, short width) { + // XXX TEMP WARNING + uiItemL(layout, "Generator FModifier UI not yet implemented again", ICON_ERROR); + +#if 0 // TODO: port to the new system FMod_Generator *data= (FMod_Generator *)fcm->data; + uiBlock *block= uiLayoutGetBlock(layout); char gen_mode[]="Generator Type%t|Expanded Polynomial%x0|Factorised Polynomial%x1"; - int cy= *yco - 30; + int cy= yco - 30; uiBut *but; - /* set the height */ - (*height) = 90; - switch (data->mode) { - case FCM_GENERATOR_POLYNOMIAL: /* polynomial expression */ - (*height) += 20*(data->poly_order+1) + 20; - break; - case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* factorised polynomial */ - (*height) += 20 * data->poly_order + 15; - break; - } - /* basic settings (backdrop + mode selector + some padding) */ - DRAW_BACKDROP((*height)); uiBlockBeginAlign(block); but= uiDefButI(block, MENU, B_FMODIFIER_REDRAW, gen_mode, 10,cy,width-30,19, &data->mode, 0, 0, 0, 0, "Selects type of generator algorithm."); uiButSetFunc(but, validate_fmodifier_cb, fcm, NULL); @@ -237,97 +230,79 @@ static void draw_modifier__generator(uiBlock *block, FModifier *fcm, int *yco, s } break; } +#endif } /* --------------- */ /* draw settings for noise modifier */ -static void draw_modifier__fn_generator(uiBlock *block, FModifier *fcm, int *yco, short *height, short width, short active, int rb_col) +static void draw_modifier__fn_generator(uiLayout *layout, FModifier *fcm, short width) { - FMod_FunctionGenerator *data= (FMod_FunctionGenerator *)fcm->data; - int cy= (*yco - 30), cy1= (*yco - 50), cy2= (*yco - 70); - char fn_type[]="Built-In Function%t|Sin%x0|Cos%x1|Tan%x2|Square Root%x3|Natural Log%x4|Normalised Sin%x5"; + uiLayout *col= uiLayoutColumn(layout, 0); // no grouping for now + PointerRNA ptr; - /* set the height */ - (*height) = 80; + /* init the RNA-pointer */ + RNA_pointer_create(NULL, &RNA_FModifierFunctionGenerator, fcm, &ptr); - /* basic settings (backdrop + some padding) */ - DRAW_BACKDROP((*height)); - - uiDefButI(block, MENU, B_FMODIFIER_REDRAW, fn_type, - 3, cy, 300, 20, &data->type, 0, 0, 0, 0, "Type of function used to generate values"); - - - uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Amplitude:", - 3, cy1, 150, 20, &data->amplitude, 0.000001, 10000.0, 0.01, 3, "Scale factor determining the maximum/minimum values."); - uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Value Offset:", - 3, cy2, 150, 20, &data->value_offset, 0.0, 10000.0, 0.01, 3, "Constant factor to offset values by."); - - uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Phase Multiplier:", - 155, cy1, 150, 20, &data->phase_multiplier, 0.0, 100000.0, 0.1, 3, "Scale factor determining the 'speed' of the function."); - uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Phase Offset:", - 155, cy2, 150, 20, &data->phase_offset, 0.0, 100000.0, 0.1, 3, "Constant factor to offset time by for function."); - + /* add the settings */ + uiItemR(col, NULL, 0, &ptr, "amplitude", 0, 0, 0); + uiItemR(col, NULL, 0, &ptr, "phase_multiplier", 0, 0, 0); + uiItemR(col, NULL, 0, &ptr, "phase_offset", 0, 0, 0); + uiItemR(col, NULL, 0, &ptr, "value_offset", 0, 0, 0); } /* --------------- */ /* draw settings for cycles modifier */ -static void draw_modifier__cycles(uiBlock *block, FModifier *fcm, int *yco, short *height, short width, short active, int rb_col) +static void draw_modifier__cycles(uiLayout *layout, FModifier *fcm, short width) { - FMod_Cycles *data= (FMod_Cycles *)fcm->data; - char cyc_mode[]="Cycling Mode%t|No Cycles%x0|Repeat Motion%x1|Repeat with Offset%x2|Repeat Mirrored%x3"; - int cy= (*yco - 30), cy1= (*yco - 50), cy2= (*yco - 70); + uiLayout *split, *col; + PointerRNA ptr; - /* set the height */ - (*height) = 80; + /* init the RNA-pointer */ + RNA_pointer_create(NULL, &RNA_FModifierCycles, fcm, &ptr); - /* basic settings (backdrop + some padding) */ - DRAW_BACKDROP((*height)); + /* split into 2 columns + * NOTE: the mode comboboxes shouldn't get labels, otherwise there isn't enough room + */ + split= uiLayoutSplit(layout, 0.5f); - /* 'before' range */ - uiDefBut(block, LABEL, 1, "Before:", 4, cy, 80, 20, NULL, 0.0, 0.0, 0, 0, "Settings for cycling before first keyframe"); - uiBlockBeginAlign(block); - uiDefButS(block, MENU, B_FMODIFIER_REDRAW, cyc_mode, 3,cy1,150,20, &data->before_mode, 0, 0, 0, 0, "Cycling mode to use before first keyframe"); - uiDefButS(block, NUM, B_FMODIFIER_REDRAW, "Max Cycles:", 3, cy2, 150, 20, &data->before_cycles, 0, 10000, 10, 3, "Maximum number of cycles to allow (0 = infinite)"); - uiBlockEndAlign(block); - - /* 'after' range */ - uiDefBut(block, LABEL, 1, "After:", 155, cy, 80, 20, NULL, 0.0, 0.0, 0, 0, "Settings for cycling after last keyframe"); - uiBlockBeginAlign(block); - uiDefButS(block, MENU, B_FMODIFIER_REDRAW, cyc_mode, 157,cy1,150,20, &data->after_mode, 0, 0, 0, 0, "Cycling mode to use after first keyframe"); - uiDefButS(block, NUM, B_FMODIFIER_REDRAW, "Max Cycles:", 157, cy2, 150, 20, &data->after_cycles, 0, 10000, 10, 3, "Maximum number of cycles to allow (0 = infinite)"); - uiBlockEndAlign(block); + /* before range */ + col= uiLayoutColumn(split, 1); + uiItemL(col, "Before:", 0); + uiItemR(col, "", 0, &ptr, "before_mode", 0, 0, 0); + uiItemR(col, NULL, 0, &ptr, "before_cycles", 0, 0, 0); + + /* after range */ + col= uiLayoutColumn(split, 1); + uiItemL(col, "After:", 0); + uiItemR(col, "", 0, &ptr, "after_mode", 0, 0, 0); + uiItemR(col, NULL, 0, &ptr, "after_cycles", 0, 0, 0); } /* --------------- */ /* draw settings for noise modifier */ -static void draw_modifier__noise(uiBlock *block, FModifier *fcm, int *yco, short *height, short width, short active, int rb_col) +static void draw_modifier__noise(uiLayout *layout, FModifier *fcm, short width) { - FMod_Noise *data= (FMod_Noise *)fcm->data; - int cy= (*yco - 30), cy1= (*yco - 50), cy2= (*yco - 70); - char blend_mode[]="Modification %t|Replace %x0|Add %x1|Subtract %x2|Multiply %x3"; + uiLayout *split, *col; + PointerRNA ptr; - /* set the height */ - (*height) = 80; + /* init the RNA-pointer */ + RNA_pointer_create(NULL, &RNA_FModifierNoise, fcm, &ptr); - /* basic settings (backdrop + some padding) */ - DRAW_BACKDROP((*height)); + /* split into 2 columns */ + split= uiLayoutSplit(layout, 0.5f); - uiDefButS(block, MENU, B_FMODIFIER_REDRAW, blend_mode, - 3, cy, 150, 20, &data->modification, 0, 0, 0, 0, "Method of combining the results of this modifier and other modifiers."); + /* col 1 */ + col= uiLayoutColumn(split, 0); + uiItemR(col, NULL, 0, &ptr, "size", 0, 0, 0); + uiItemR(col, NULL, 0, &ptr, "strength", 0, 0, 0); - uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Size:", - 3, cy1, 150, 20, &data->size, 0.000001, 10000.0, 0.01, 3, ""); - uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Strength:", - 3, cy2, 150, 20, &data->strength, 0.0, 10000.0, 0.01, 3, ""); - - uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Phase:", - 155, cy1, 150, 20, &data->phase, 0.0, 100000.0, 0.1, 3, ""); - uiDefButS(block, NUM, B_FMODIFIER_REDRAW, "Depth:", - 155, cy2, 150, 20, &data->depth, 0, 128, 1, 3, ""); - + /* col 2 */ + col= uiLayoutColumn(split, 0); + uiItemR(col, NULL, 0, &ptr, "phase", 0, 0, 0); + uiItemR(col, NULL, 0, &ptr, "depth", 0, 0, 0); } /* --------------- */ @@ -492,22 +467,17 @@ static void fmod_envelope_deletepoint_cb (bContext *C, void *fcm_dv, void *ind_v } /* draw settings for envelope modifier */ -static void draw_modifier__envelope(uiBlock *block, FModifier *fcm, int *yco, short *height, short width, short active, int rb_col) +static void draw_modifier__envelope(uiLayout *layout, FModifier *fcm, short width) { + uiItemL(layout, "Envelope FModifier UI not yet recoded in layout engine", ICON_ERROR); +#if 0 // XXX FIXME: recode in new layout style FMod_Envelope *env= (FMod_Envelope *)fcm->data; FCM_EnvelopeData *fed; + uiBlock *block= uiLayoutGetBlock(layout); uiBut *but; - int cy= (*yco - 28); + int cy= (yco - 28); int i; - /* set the height: - * - basic settings + variable height from envelope controls - */ - (*height) = 115 + (35 * env->totvert); - - /* basic settings (backdrop + general settings + some padding) */ - DRAW_BACKDROP((*height)); - /* General Settings */ uiDefBut(block, LABEL, 1, "Envelope:", 10, cy, 100, 20, NULL, 0.0, 0.0, 0, 0, "Settings for cycling before first keyframe"); cy -= 20; @@ -543,83 +513,104 @@ static void draw_modifier__envelope(uiBlock *block, FModifier *fcm, int *yco, sh uiBlockBeginAlign(block); cy -= 25; } +#endif } /* --------------- */ /* draw settings for limits modifier */ -static void draw_modifier__limits(uiBlock *block, FModifier *fcm, int *yco, short *height, short width, short active, int rb_col) +static void draw_modifier__limits(uiLayout *layout, FModifier *fcm, short width) { - FMod_Limits *data= (FMod_Limits *)fcm->data; - const int togButWidth = 50; - const int textButWidth = ((width/2)-togButWidth); + uiLayout *split, *col, *row; + PointerRNA ptr; - /* set the height */ - (*height) = 60; + /* init the RNA-pointer */ + RNA_pointer_create(NULL, &RNA_FModifierLimits, fcm, &ptr); - /* basic settings (backdrop + some padding) */ - DRAW_BACKDROP((*height)); + /* row 1: minimum */ + { + row= uiLayoutRow(layout, 0); + + /* split into 2 columns */ + split= uiLayoutSplit(layout, 0.5f); + + /* x-minimum */ + col= uiLayoutColumn(split, 1); + uiItemR(col, NULL, 0, &ptr, "use_minimum_x", 0, 0, 0); + uiItemR(col, NULL, 0, &ptr, "minimum_x", 0, 0, 0); + + /* y-minimum*/ + col= uiLayoutColumn(split, 1); + uiItemR(col, NULL, 0, &ptr, "use_minimum_y", 0, 0, 0); + uiItemR(col, NULL, 0, &ptr, "minimum_y", 0, 0, 0); + } - /* Draw Pairs of LimitToggle+LimitValue */ - uiBlockBeginAlign(block); - uiDefButBitI(block, TOGBUT, FCM_LIMIT_XMIN, B_FMODIFIER_REDRAW, "xMin", 5, *yco-30, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum x value"); - uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 5+togButWidth, *yco-30, (textButWidth-5), 18, &data->rect.xmin, -UI_FLT_MAX, UI_FLT_MAX, 0.1,0.5,"Lowest x value to allow"); - uiBlockEndAlign(block); - - uiBlockBeginAlign(block); - uiDefButBitI(block, TOGBUT, FCM_LIMIT_XMAX, B_FMODIFIER_REDRAW, "XMax", 5+(width-(textButWidth-5)-togButWidth), *yco-30, 50, 18, &data->flag, 0, 24, 0, 0, "Use maximum x value"); - uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 5+(width-textButWidth-5), *yco-30, (textButWidth-5), 18, &data->rect.xmax, -UI_FLT_MAX, UI_FLT_MAX, 0.1,0.5,"Highest x value to allow"); - uiBlockEndAlign(block); - - uiBlockBeginAlign(block); - uiDefButBitI(block, TOGBUT, FCM_LIMIT_YMIN, B_FMODIFIER_REDRAW, "yMin", 5, *yco-52, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum y value"); - uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 5+togButWidth, *yco-52, (textButWidth-5), 18, &data->rect.ymin, -UI_FLT_MAX, UI_FLT_MAX, 0.1,0.5,"Lowest y value to allow"); - uiBlockEndAlign(block); - - uiBlockBeginAlign(block); - uiDefButBitI(block, TOGBUT, FCM_LIMIT_YMAX, B_FMODIFIER_REDRAW, "YMax", 5+(width-(textButWidth-5)-togButWidth), *yco-52, 50, 18, &data->flag, 0, 24, 0, 0, "Use maximum y value"); - uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 5+(width-textButWidth-5), *yco-52, (textButWidth-5), 18, &data->rect.ymax, -UI_FLT_MAX, UI_FLT_MAX, 0.1,0.5,"Highest y value to allow"); - uiBlockEndAlign(block); + /* row 2: minimum */ + { + row= uiLayoutRow(layout, 0); + + /* split into 2 columns */ + split= uiLayoutSplit(layout, 0.5f); + + /* x-minimum */ + col= uiLayoutColumn(split, 1); + uiItemR(col, NULL, 0, &ptr, "use_maximum_x", 0, 0, 0); + uiItemR(col, NULL, 0, &ptr, "maximum_x", 0, 0, 0); + + /* y-minimum*/ + col= uiLayoutColumn(split, 1); + uiItemR(col, NULL, 0, &ptr, "use_maximum_y", 0, 0, 0); + uiItemR(col, NULL, 0, &ptr, "maximum_y", 0, 0, 0); + } } /* --------------- */ -// FIXME: remove dependency for F-Curve -void ANIM_uiTemplate_fmodifier_draw (uiBlock *block, ListBase *modifiers, FModifier *fcm, int *yco) + +void ANIM_uiTemplate_fmodifier_draw (uiLayout *layout, ListBase *modifiers, FModifier *fcm) { FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); + uiLayout *box, *row, *subrow; + uiBlock *block; uiBut *but; - short active= (fcm->flag & FMODIFIER_FLAG_ACTIVE); short width= 314; - short height = 0; - int rb_col; /* draw header */ { + /* get layout-row + UI-block for this */ + box= uiLayoutBox(layout); + + row= uiLayoutRow(box, 0); + block= uiLayoutGetBlock(row); // err... + uiBlockSetEmboss(block, UI_EMBOSSN); - /* rounded header */ - rb_col= (active)?-20:20; - but= uiDefBut(block, ROUNDBOX, B_REDR, "", 0, *yco-2, width, 24, NULL, 5.0, 0.0, 15.0, (float)(rb_col-20), ""); + /* left-align -------------------------------------------- */ + subrow= uiLayoutRow(row, 0); + uiLayoutSetAlignment(subrow, UI_LAYOUT_ALIGN_LEFT); /* expand */ - uiDefIconButBitS(block, ICONTOG, FMODIFIER_FLAG_EXPANDED, B_REDR, ICON_TRIA_RIGHT, 5, *yco-1, 20, 20, &fcm->flag, 0.0, 0.0, 0, 0, "Modifier is expanded."); + uiDefIconButBitS(block, ICONTOG, FMODIFIER_FLAG_EXPANDED, B_REDR, ICON_TRIA_RIGHT, 0, -1, UI_UNIT_X, UI_UNIT_Y, &fcm->flag, 0.0, 0.0, 0, 0, "Modifier is expanded."); /* checkbox for 'active' status (for now) */ - but= uiDefIconButBitS(block, ICONTOG, FMODIFIER_FLAG_ACTIVE, B_REDR, ICON_RADIOBUT_OFF, 25, *yco-1, 20, 20, &fcm->flag, 0.0, 0.0, 0, 0, "Modifier is active one."); + but= uiDefIconButBitS(block, ICONTOG, FMODIFIER_FLAG_ACTIVE, B_REDR, ICON_RADIOBUT_OFF, 0, -1, UI_UNIT_X, UI_UNIT_Y, &fcm->flag, 0.0, 0.0, 0, 0, "Modifier is active one."); uiButSetFunc(but, activate_fmodifier_cb, modifiers, fcm); /* name */ if (fmi) - uiDefBut(block, LABEL, 1, fmi->name, 10+40, *yco, 150, 20, NULL, 0.0, 0.0, 0, 0, "F-Curve Modifier Type. Click to make modifier active one."); + uiDefBut(block, LABEL, 1, fmi->name, 0, 0, 150, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "F-Curve Modifier Type. Click to make modifier active one."); else - uiDefBut(block, LABEL, 1, "", 10+40, *yco, 150, 20, NULL, 0.0, 0.0, 0, 0, "F-Curve Modifier Type. Click to make modifier active one."); + uiDefBut(block, LABEL, 1, "", 0, 0, 150, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "F-Curve Modifier Type. Click to make modifier active one."); + + /* right-align ------------------------------------------- */ + subrow= uiLayoutRow(row, 0); + uiLayoutSetAlignment(subrow, UI_LAYOUT_ALIGN_RIGHT); /* 'mute' button */ - uiDefIconButBitS(block, ICONTOG, FMODIFIER_FLAG_MUTED, B_REDR, ICON_MUTE_IPO_OFF, 10+(width-60), *yco-1, 20, 20, &fcm->flag, 0.0, 0.0, 0, 0, "Modifier is temporarily muted (not evaluated)."); + uiDefIconButBitS(block, ICONTOG, FMODIFIER_FLAG_MUTED, B_REDR, ICON_MUTE_IPO_OFF, 0, 0, UI_UNIT_X, UI_UNIT_Y, &fcm->flag, 0.0, 0.0, 0, 0, "Modifier is temporarily muted (not evaluated)."); /* delete button */ - but= uiDefIconBut(block, BUT, B_REDR, ICON_X, 10+(width-30), *yco, 19, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Delete F-Curve Modifier."); + but= uiDefIconBut(block, BUT, B_REDR, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, "Delete F-Curve Modifier."); uiButSetFunc(but, delete_fmodifier_cb, modifiers, fcm); uiBlockSetEmboss(block, UI_EMBOSS); @@ -627,43 +618,39 @@ void ANIM_uiTemplate_fmodifier_draw (uiBlock *block, ListBase *modifiers, FModif /* when modifier is expanded, draw settings */ if (fcm->flag & FMODIFIER_FLAG_EXPANDED) { + /* set up the flexible-box layout which acts as the backdrop for the modifier settings */ + box= uiLayoutBox(layout); + /* draw settings for individual modifiers */ switch (fcm->type) { case FMODIFIER_TYPE_GENERATOR: /* Generator */ - draw_modifier__generator(block, fcm, yco, &height, width, active, rb_col); + draw_modifier__generator(box, fcm, width); break; case FMODIFIER_TYPE_FN_GENERATOR: /* Built-In Function Generator */ - draw_modifier__fn_generator(block, fcm, yco, &height, width, active, rb_col); + draw_modifier__fn_generator(box, fcm, width); break; case FMODIFIER_TYPE_CYCLES: /* Cycles */ - draw_modifier__cycles(block, fcm, yco, &height, width, active, rb_col); + draw_modifier__cycles(box, fcm, width); break; case FMODIFIER_TYPE_ENVELOPE: /* Envelope */ - draw_modifier__envelope(block, fcm, yco, &height, width, active, rb_col); + draw_modifier__envelope(box, fcm, width); break; case FMODIFIER_TYPE_LIMITS: /* Limits */ - draw_modifier__limits(block, fcm, yco, &height, width, active, rb_col); + draw_modifier__limits(box, fcm, width); break; case FMODIFIER_TYPE_NOISE: /* Noise */ - draw_modifier__noise(block, fcm, yco, &height, width, active, rb_col); + draw_modifier__noise(box, fcm, width); break; default: /* unknown type */ - height= 96; - //DRAW_BACKDROP(height); // XXX buggy... break; } } - - /* adjust height for new to start */ - (*yco) -= (height + 27); } /* ********************************************** */ - - \ No newline at end of file diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index 87f05c8a76a..df4e704cae8 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -296,11 +296,11 @@ void ANIM_draw_previewrange(const struct bContext *C, struct View2D *v2d); /* ************************************************* */ /* F-MODIFIER TOOLS */ -struct uiBlock; +struct uiLayout; /* draw a given F-Modifier for some layout/UI-Block */ // XXX not quite complete yet -void ANIM_uiTemplate_fmodifier_draw(struct uiBlock *block, ListBase *modifiers, struct FModifier *fcm, int *yco); +void ANIM_uiTemplate_fmodifier_draw(struct uiLayout *layout, ListBase *modifiers, struct FModifier *fcm); /* ************************************************* */ /* ASSORTED TOOLS */ diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c index 5616ffc8002..17bc78f9ee6 100644 --- a/source/blender/editors/space_graph/graph_buttons.c +++ b/source/blender/editors/space_graph/graph_buttons.c @@ -366,22 +366,30 @@ static void graph_panel_modifiers(const bContext *C, Panel *pa) bAnimListElem *ale; FCurve *fcu; FModifier *fcm; + uiLayout *col, *row; uiBlock *block; - int yco= 190; - if(!graph_panel_context(C, &ale, &fcu)) + if (!graph_panel_context(C, &ale, &fcu)) return; - block= uiLayoutFreeBlock(pa->layout); + block= uiLayoutGetBlock(pa->layout); uiBlockSetHandleFunc(block, do_graph_region_modifier_buttons, NULL); /* 'add modifier' button at top of panel */ - // XXX for now, this will be a operator button which calls a temporary 'add modifier' operator - uiDefButO(block, BUT, "GRAPH_OT_fmodifier_add", WM_OP_INVOKE_REGION_WIN, "Add Modifier", 10, 225, 150, 20, "Adds a new F-Curve Modifier for the active F-Curve"); + { + row= uiLayoutRow(pa->layout, 0); + block= uiLayoutGetBlock(row); + + // XXX for now, this will be a operator button which calls a temporary 'add modifier' operator + uiDefButO(block, BUT, "GRAPH_OT_fmodifier_add", WM_OP_INVOKE_REGION_WIN, "Add Modifier", 10, 0, 150, 20, "Adds a new F-Curve Modifier for the active F-Curve"); + } /* draw each modifier */ - for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next) - ANIM_uiTemplate_fmodifier_draw(block, &fcu->modifiers, fcm, &yco); + for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next) { + col= uiLayoutColumn(pa->layout, 1); + + ANIM_uiTemplate_fmodifier_draw(col, &fcu->modifiers, fcm); + } MEM_freeN(ale); } diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c index 1ef72760bfc..67c4365ff49 100644 --- a/source/blender/editors/space_nla/nla_buttons.c +++ b/source/blender/editors/space_nla/nla_buttons.c @@ -311,26 +311,33 @@ static void nla_panel_modifiers(const bContext *C, Panel *pa) PointerRNA strip_ptr; NlaStrip *strip; FModifier *fcm; - uiLayout *layout= pa->layout; + uiLayout *col, *row; uiBlock *block; - int yco = 190; // xxx old /* check context and also validity of pointer */ if (!nla_panel_context(C, NULL, &strip_ptr)) return; strip= strip_ptr.data; - block= uiLayoutGetBlock(layout); + block= uiLayoutGetBlock(pa->layout); uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL); /* 'add modifier' button at top of panel */ - // XXX for now, this will be a operator button which calls a temporary 'add modifier' operator - // FIXME: we need to set the only-active property so that this will only add modifiers for the active strip (not all selected) - uiDefButO(block, BUT, "NLA_OT_fmodifier_add", WM_OP_INVOKE_REGION_WIN, "Add Modifier", 10, 225, 150, 20, "Adds a new F-Modifier for the active NLA Strip"); + { + row= uiLayoutRow(pa->layout, 0); + block= uiLayoutGetBlock(row); + + // XXX for now, this will be a operator button which calls a temporary 'add modifier' operator + // FIXME: we need to set the only-active property so that this will only add modifiers for the active strip (not all selected) + uiDefButO(block, BUT, "NLA_OT_fmodifier_add", WM_OP_INVOKE_REGION_WIN, "Add Modifier", 10, 0, 150, 20, "Adds a new F-Modifier for the active NLA Strip"); + } /* draw each modifier */ - for (fcm= strip->modifiers.first; fcm; fcm= fcm->next) - ANIM_uiTemplate_fmodifier_draw(block, &strip->modifiers, fcm, &yco); + for (fcm= strip->modifiers.first; fcm; fcm= fcm->next) { + col= uiLayoutColumn(pa->layout, 1); + + ANIM_uiTemplate_fmodifier_draw(col, &strip->modifiers, fcm); + } } /* ******************* general ******************************** */ diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 106185085d6..0673521505f 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -179,6 +179,7 @@ extern StructRNA RNA_FileSelectParams; extern StructRNA RNA_FModifier; extern StructRNA RNA_FModifierCycles; extern StructRNA RNA_FModifierEnvelope; +extern StructRNA RNA_FModifierEnvelopeControlPoint; extern StructRNA RNA_FModifierFunctionGenerator; extern StructRNA RNA_FModifierGenerator; extern StructRNA RNA_FModifierGenerator_PolyExpanded; diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c index 826d186516d..95a0482557f 100644 --- a/source/blender/makesrna/intern/rna_fcurve.c +++ b/source/blender/makesrna/intern/rna_fcurve.c @@ -56,17 +56,7 @@ StructRNA *rna_FModifierType_refine(struct PointerRNA *ptr) switch (fcm->type) { case FMODIFIER_TYPE_GENERATOR: - { - FMod_Generator *gen= (FMod_Generator *)fcm->data; - - switch (gen->mode) { - case FCM_GENERATOR_POLYNOMIAL: - return &RNA_FModifierGenerator_PolyExpanded; - //case FCM_GENERATOR_POLYNOMIAL_FACTORISED: - default: - return &RNA_FModifierGenerator; - } - } + return &RNA_FModifierGenerator; case FMODIFIER_TYPE_FN_GENERATOR: return &RNA_FModifierFunctionGenerator; case FMODIFIER_TYPE_ENVELOPE: @@ -159,19 +149,22 @@ static void rna_FCurve_RnaPath_set(PointerRNA *ptr, const char *value) #else -static void rna_def_fmodifier_generator_common(StructRNA *srna) + +static void rna_def_fmodifier_generator(BlenderRNA *brna) { + StructRNA *srna; PropertyRNA *prop; static EnumPropertyItem prop_mode_items[] = { {FCM_GENERATOR_POLYNOMIAL, "POLYNOMIAL", 0, "Expanded Polynomial", ""}, {FCM_GENERATOR_POLYNOMIAL_FACTORISED, "POLYNOMIAL_FACTORISED", 0, "Factorised Polynomial", ""}, {0, NULL, 0, NULL, NULL}}; - - /* struct wrapping settings */ - RNA_def_struct_sdna_from(srna, "FMod_Generator", "data"); - /* settings */ + srna= RNA_def_struct(brna, "FModifierGenerator", "FModifier"); + RNA_def_struct_ui_text(srna, "Generator F-Curve Modifier", "Deterministically generates values for the modified F-Curve."); + RNA_def_struct_sdna_from(srna, "FMod_Generator", "data"); + + /* define common props */ prop= RNA_def_property(srna, "additive", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", FCM_GENERATOR_ADDITIVE); RNA_def_property_ui_text(prop, "Additive", "Values generated by this modifier are applied on top of the existing values instead of overwriting them."); @@ -180,41 +173,22 @@ static void rna_def_fmodifier_generator_common(StructRNA *srna) prop= RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, prop_mode_items); RNA_def_property_ui_text(prop, "Mode", "Type of generator to use."); -} - -/* this is a temporary dummy generator-modifier wrapping (to be discarded) */ -static void rna_def_fmodifier_generator(BlenderRNA *brna) -{ - StructRNA *srna; - srna= RNA_def_struct(brna, "FModifierGenerator", "FModifier"); - RNA_def_struct_ui_text(srna, "Generator F-Curve Modifier", "Deterministically generates values for the modified F-Curve."); - - /* define common props */ - rna_def_fmodifier_generator_common(srna); -} - -static void rna_def_fmodifier_generator_polyexpanded(BlenderRNA *brna) -{ - StructRNA *srna; - PropertyRNA *prop; - - srna= RNA_def_struct(brna, "FModifierGenerator_PolyExpanded", "FModifier"); - RNA_def_struct_ui_text(srna, "Expanded Polynomial Generator", "Generates values for the modified F-Curve using expanded polynomial expresion."); - - /* define common props */ - rna_def_fmodifier_generator_common(srna); /* order of the polynomial */ // XXX this has a special validation func prop= RNA_def_property(srna, "poly_order", PROP_INT, PROP_NONE); - RNA_def_property_ui_text(prop, "Polynomial Order", "The highest power of 'x' for this polynomial. (i.e. the number of coefficients - 1)"); + RNA_def_property_ui_text(prop, "Polynomial Order", "The highest power of 'x' for this polynomial. (number of coefficients - 1)"); /* coefficients array */ - //prop= RNA_def_property(srna, "coefficients", PROP_FLOAT, PROP_NONE); - //RNA_def_property_ui_text(prop, "Coefficients", "Coefficients for 'x' (starting from lowest power)."); + // FIXME: this is quite difficult to try to wrap + //prop= RNA_def_property(srna, "coefficients", PROP_COLLECTION, PROP_NONE); + //RNA_def_property_collection_funcs(prop, "rna_FModifierGenerator_coefficients_begin", "rna_FModifierGenerator_coefficients_next", "rna_FModifierGenerator_coefficients_end", "rna_iterator_array_get", "rna_FModifierGenerator_coefficients_length", 0, 0, 0, 0); + //RNA_def_property_ui_text(prop, "Coefficients", "Coefficients for 'x' (starting from lowest power of x^0)."); } +/* --------- */ + static void rna_def_fmodifier_function_generator(BlenderRNA *brna) { StructRNA *srna; @@ -258,14 +232,63 @@ static void rna_def_fmodifier_function_generator(BlenderRNA *brna) /* --------- */ +static void rna_def_fmodifier_envelope_ctrl(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna= RNA_def_struct(brna, "FModifierEnvelopeControlPoint", NULL); + RNA_def_struct_ui_text(srna, "Envelope Control Point", "Control point for envelope F-Modifier."); + RNA_def_struct_sdna(srna, "FCM_EnvelopeData"); + + /* min/max extents + * - for now, these are allowed to go past each other, so that we can have inverted action + * - technically, the range is limited by the settings in the envelope-modifier data, not here... + */ + prop= RNA_def_property(srna, "minimum", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "min"); + RNA_def_property_ui_text(prop, "Minimum Value", "Lower bound of envelope at this control-point."); + + prop= RNA_def_property(srna, "maximum", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "max"); + RNA_def_property_ui_text(prop, "Maximum Value", "Upper bound of envelope at this control-point."); + + /* Frame */ + prop= RNA_def_property(srna, "frame", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "time"); + RNA_def_property_ui_text(prop, "Frame", "Frame this control-point occurs on."); + + // TODO: + // - selection flags (not implemented in UI yet though) +} + static void rna_def_fmodifier_envelope(BlenderRNA *brna) { StructRNA *srna; - //PropertyRNA *prop; + PropertyRNA *prop; srna= RNA_def_struct(brna, "FModifierEnvelope", "FModifier"); RNA_def_struct_ui_text(srna, "Envelope F-Modifier", "Scales the values of the modified F-Curve."); RNA_def_struct_sdna_from(srna, "FMod_Envelope", "data"); + + /* Collections */ + prop= RNA_def_property(srna, "control_points", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "data", "totvert"); + RNA_def_property_struct_type(prop, "FModifierEnvelopeControlPoint"); + RNA_def_property_ui_text(prop, "Control Points", "Control points defining the shape of the envelope."); + + /* Range Settings */ + prop= RNA_def_property(srna, "reference_value", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "midval"); + RNA_def_property_ui_text(prop, "Reference Value", "Value that envelope's influence is centered around / based on."); + + prop= RNA_def_property(srna, "default_minimum", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "min"); + RNA_def_property_ui_text(prop, "Default Minimum", "Lower distance from Reference Value for 1:1 default influence."); + + prop= RNA_def_property(srna, "default_maximum", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "max"); + RNA_def_property_ui_text(prop, "Default Maximum", "Upper distance from Reference Value for 1:1 default influence."); } /* --------- */ @@ -606,9 +629,9 @@ void RNA_def_fcurve(BlenderRNA *brna) rna_def_fmodifier(brna); rna_def_fmodifier_generator(brna); - rna_def_fmodifier_generator_polyexpanded(brna); rna_def_fmodifier_function_generator(brna); rna_def_fmodifier_envelope(brna); + rna_def_fmodifier_envelope_ctrl(brna); rna_def_fmodifier_cycles(brna); rna_def_fmodifier_python(brna); rna_def_fmodifier_limits(brna); From e9c85406e4f24eeab8818b3b58862c3798c0dc14 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 2 Jul 2009 23:27:11 +0000 Subject: [PATCH 081/114] NLA SoC: UI-Drawing for Generator and Envelope FModifiers Restored These now use a hybrid drawing approach - using the layout engine for just layouts, but still mostly using old-style buttons in many places where button callbacks and/or special data-access methods are needed (or where RNA wrapping isn't in place yet). --- .../blender/editors/animation/fmodifier_ui.c | 159 ++++++++++-------- 1 file changed, 87 insertions(+), 72 deletions(-) diff --git a/source/blender/editors/animation/fmodifier_ui.c b/source/blender/editors/animation/fmodifier_ui.c index 19c7d049758..3be96031526 100644 --- a/source/blender/editors/animation/fmodifier_ui.c +++ b/source/blender/editors/animation/fmodifier_ui.c @@ -136,24 +136,23 @@ static void delete_fmodifier_cb (bContext *C, void *fmods_v, void *fcm_v) /* draw settings for generator modifier */ static void draw_modifier__generator(uiLayout *layout, FModifier *fcm, short width) { - // XXX TEMP WARNING - uiItemL(layout, "Generator FModifier UI not yet implemented again", ICON_ERROR); - -#if 0 // TODO: port to the new system FMod_Generator *data= (FMod_Generator *)fcm->data; - uiBlock *block= uiLayoutGetBlock(layout); - char gen_mode[]="Generator Type%t|Expanded Polynomial%x0|Factorised Polynomial%x1"; - int cy= yco - 30; + uiLayout *col, *row; + uiBlock *block; uiBut *but; + PointerRNA ptr; + + /* init the RNA-pointer */ + RNA_pointer_create(NULL, &RNA_FModifierFunctionGenerator, fcm, &ptr); /* basic settings (backdrop + mode selector + some padding) */ + col= uiLayoutColumn(layout, 1); + block= uiLayoutGetBlock(layout); uiBlockBeginAlign(block); - but= uiDefButI(block, MENU, B_FMODIFIER_REDRAW, gen_mode, 10,cy,width-30,19, &data->mode, 0, 0, 0, 0, "Selects type of generator algorithm."); + but= uiDefButR(block, MENU, B_FMODIFIER_REDRAW, NULL, 0, 0, width-30, UI_UNIT_Y, &ptr, "mode", -1, 0, 0, -1, -1, NULL); uiButSetFunc(but, validate_fmodifier_cb, fcm, NULL); - cy -= 20; - uiDefButBitI(block, TOG, FCM_GENERATOR_ADDITIVE, B_FMODIFIER_REDRAW, "Additive", 10,cy,width-30,19, &data->flag, 0, 0, 0, 0, "Values generated by this modifier are applied on top of the existing values instead of overwriting them"); - cy -= 35; + uiDefButR(block, TOG, B_FMODIFIER_REDRAW, NULL, 0, 0, width-30, UI_UNIT_Y, &ptr, "additive", -1, 0, 0, -1, -1, NULL); uiBlockEndAlign(block); /* now add settings for individual modes */ @@ -165,31 +164,38 @@ static void draw_modifier__generator(uiLayout *layout, FModifier *fcm, short wid unsigned int i; /* draw polynomial order selector */ - but= uiDefButI(block, NUM, B_FMODIFIER_REDRAW, "Poly Order: ", 10,cy,width-30,19, &data->poly_order, 1, 100, 0, 0, "'Order' of the Polynomial - for a polynomial with n terms, 'order' is n-1"); - uiButSetFunc(but, validate_fmodifier_cb, fcm, NULL); - cy -= 35; + row= uiLayoutRow(layout, 0); + block= uiLayoutGetBlock(row); + but= uiDefButI(block, NUM, B_FMODIFIER_REDRAW, "Poly Order: ", 10,0,width-30,19, &data->poly_order, 1, 100, 0, 0, "'Order' of the Polynomial - for a polynomial with n terms, 'order' is n-1"); + uiButSetFunc(but, validate_fmodifier_cb, fcm, NULL); + /* draw controls for each coefficient and a + sign at end of row */ - uiDefBut(block, LABEL, 1, "y = ", 0, cy, 50, 20, NULL, 0.0, 0.0, 0, 0, ""); + row= uiLayoutRow(layout, 1); + block= uiLayoutGetBlock(row); + uiDefBut(block, LABEL, 1, "y = ", 0, 0, 50, 20, NULL, 0.0, 0.0, 0, 0, ""); cp= data->coefficients; for (i=0; (i < data->arraysize) && (cp); i++, cp++) { /* coefficient */ - uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 50, cy, 150, 20, cp, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "Coefficient for polynomial"); + uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 0, 0, 150, 20, cp, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "Coefficient for polynomial"); /* 'x' param (and '+' if necessary) */ - if (i == 0) - strcpy(xval, ""); - else if (i == 1) - strcpy(xval, "x"); - else - sprintf(xval, "x^%d", i); - uiDefBut(block, LABEL, 1, xval, 200, cy, 50, 20, NULL, 0.0, 0.0, 0, 0, "Power of x"); + if (i) { + if (i == 1) + strcpy(xval, "x"); + else + sprintf(xval, "x^%d", i); + uiDefBut(block, LABEL, 1, xval, 0, 0, 50, 20, NULL, 0.0, 0.0, 0, 0, "Power of x"); + } - if ( (i != (data->arraysize - 1)) || ((i==0) && data->arraysize==2) ) - uiDefBut(block, LABEL, 1, "+", 250, cy, 30, 20, NULL, 0.0, 0.0, 0, 0, ""); - - cy -= 20; + if ( (i != (data->arraysize - 1)) || ((i==0) && data->arraysize==2) ) { + uiDefBut(block, LABEL, 1, "+", 0,0 , 30, 20, NULL, 0.0, 0.0, 0, 0, ""); + + /* next coefficient on a new row */ + row= uiLayoutRow(layout, 1); + block= uiLayoutGetBlock(row); + } } } break; @@ -200,37 +206,43 @@ static void draw_modifier__generator(uiLayout *layout, FModifier *fcm, short wid unsigned int i; /* draw polynomial order selector */ - but= uiDefButI(block, NUM, B_FMODIFIER_REDRAW, "Poly Order: ", 10,cy,width-30,19, &data->poly_order, 1, 100, 0, 0, "'Order' of the Polynomial - for a polynomial with n terms, 'order' is n-1"); - uiButSetFunc(but, validate_fmodifier_cb, fcm, NULL); - cy -= 35; + row= uiLayoutRow(layout, 0); + block= uiLayoutGetBlock(row); + but= uiDefButI(block, NUM, B_FMODIFIER_REDRAW, "Poly Order: ", 0,0,width-30,19, &data->poly_order, 1, 100, 0, 0, "'Order' of the Polynomial - for a polynomial with n terms, 'order' is n-1"); + uiButSetFunc(but, validate_fmodifier_cb, fcm, NULL); + /* draw controls for each pair of coefficients */ - uiDefBut(block, LABEL, 1, "y = ", 0, cy, 50, 20, NULL, 0.0, 0.0, 0, 0, ""); + row= uiLayoutRow(layout, 1); + block= uiLayoutGetBlock(row); + uiDefBut(block, LABEL, 1, "y = ", 0, 0, 50, 20, NULL, 0.0, 0.0, 0, 0, ""); cp= data->coefficients; for (i=0; (i < data->poly_order) && (cp); i++, cp+=2) { /* opening bracket */ - uiDefBut(block, LABEL, 1, "(", 40, cy, 50, 20, NULL, 0.0, 0.0, 0, 0, ""); + uiDefBut(block, LABEL, 1, "(", 0, 0, 20, 20, NULL, 0.0, 0.0, 0, 0, ""); /* coefficients */ - uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 50, cy, 100, 20, cp, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "Coefficient of x"); + uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 0, 0, 100, 20, cp, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "Coefficient of x"); - uiDefBut(block, LABEL, 1, "x + ", 150, cy, 30, 20, NULL, 0.0, 0.0, 0, 0, ""); + uiDefBut(block, LABEL, 1, "x + ", 0, 0, 40, 20, NULL, 0.0, 0.0, 0, 0, ""); - uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 180, cy, 100, 20, cp+1, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "Second coefficient"); + uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 0, 0, 100, 20, cp+1, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "Second coefficient"); /* closing bracket and '+' sign */ - if ( (i != (data->poly_order - 1)) || ((i==0) && data->poly_order==2) ) - uiDefBut(block, LABEL, 1, ") ?", 280, cy, 30, 20, NULL, 0.0, 0.0, 0, 0, ""); - else - uiDefBut(block, LABEL, 1, ")", 280, cy, 30, 20, NULL, 0.0, 0.0, 0, 0, ""); - - cy -= 20; + if ( (i != (data->poly_order - 1)) || ((i==0) && data->poly_order==2) ) { + uiDefBut(block, LABEL, 1, ") +", 0, 0, 30, 20, NULL, 0.0, 0.0, 0, 0, ""); + + /* set up new row for the next pair of coefficients*/ + row= uiLayoutRow(layout, 1); + block= uiLayoutGetBlock(row); + } + else + uiDefBut(block, LABEL, 1, ")", 0, 0, 20, 20, NULL, 0.0, 0.0, 0, 0, ""); } } break; } -#endif } /* --------------- */ @@ -469,51 +481,54 @@ static void fmod_envelope_deletepoint_cb (bContext *C, void *fcm_dv, void *ind_v /* draw settings for envelope modifier */ static void draw_modifier__envelope(uiLayout *layout, FModifier *fcm, short width) { - uiItemL(layout, "Envelope FModifier UI not yet recoded in layout engine", ICON_ERROR); -#if 0 // XXX FIXME: recode in new layout style FMod_Envelope *env= (FMod_Envelope *)fcm->data; FCM_EnvelopeData *fed; - uiBlock *block= uiLayoutGetBlock(layout); + uiLayout *col, *row; + uiBlock *block; uiBut *but; - int cy= (yco - 28); + PointerRNA ptr; int i; - /* General Settings */ - uiDefBut(block, LABEL, 1, "Envelope:", 10, cy, 100, 20, NULL, 0.0, 0.0, 0, 0, "Settings for cycling before first keyframe"); - cy -= 20; + /* init the RNA-pointer */ + RNA_pointer_create(NULL, &RNA_FModifierEnvelope, fcm, &ptr); - uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Reference Val:", 10, cy, 300, 20, &env->midval, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, ""); - cy -= 20; + /* general settings */ + col= uiLayoutColumn(layout, 1); + uiItemL(col, "Envelope:", 0); + uiItemR(col, NULL, 0, &ptr, "reference_value", 0, 0, 0); - uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Min:", 10, cy, 150, 20, &env->min, -UI_FLT_MAX, env->max, 10, 3, "Minimum value (relative to Reference Value) that is used as the 'normal' minimum value"); - uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Max:", 160, cy, 150, 20, &env->max, env->min, UI_FLT_MAX, 10, 3, "Maximum value (relative to Reference Value) that is used as the 'normal' maximum value"); - cy -= 35; - uiBlockEndAlign(block); - - - /* Points header */ - uiDefBut(block, LABEL, 1, "Control Points:", 10, cy, 150, 20, NULL, 0.0, 0.0, 0, 0, ""); - - but= uiDefBut(block, BUT, B_FMODIFIER_REDRAW, "Add Point", 160,cy,150,19, NULL, 0, 0, 0, 0, "Adds a new control-point to the envelope on the current frame"); - uiButSetFunc(but, fmod_envelope_addpoint_cb, env, NULL); - cy -= 35; - - /* Points List */ + row= uiLayoutRow(col, 1); + uiItemR(row, "Min", 0, &ptr, "default_minimum", 0, 0, 0); + uiItemR(row, "Max", 0, &ptr, "default_maximum", 0, 0, 0); + + /* control points header */ + // TODO: move this control-point control stuff to using the new special widgets for lists + // the current way is far too cramped + row= uiLayoutRow(layout, 0); + block= uiLayoutGetBlock(row); + + uiDefBut(block, LABEL, 1, "Control Points:", 0, 0, 150, 20, NULL, 0.0, 0.0, 0, 0, ""); + + but= uiDefBut(block, BUT, B_FMODIFIER_REDRAW, "Add Point", 0,0,150,19, NULL, 0, 0, 0, 0, "Adds a new control-point to the envelope on the current frame"); + uiButSetFunc(but, fmod_envelope_addpoint_cb, env, NULL); + + /* control points list */ for (i=0, fed=env->data; i < env->totvert; i++, fed++) { + /* get a new row to operate on */ + row= uiLayoutRow(layout, 1); + block= uiLayoutGetBlock(row); + uiBlockBeginAlign(block); - but=uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Fra:", 2, cy, 90, 20, &fed->time, -UI_FLT_MAX, UI_FLT_MAX, 10, 1, "Frame that envelope point occurs"); + but=uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Fra:", 0, 0, 90, 20, &fed->time, -UI_FLT_MAX, UI_FLT_MAX, 10, 1, "Frame that envelope point occurs"); uiButSetFunc(but, validate_fmodifier_cb, fcm, NULL); - uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Min:", 92, cy, 100, 20, &fed->min, -UI_FLT_MAX, UI_FLT_MAX, 10, 2, "Minimum bound of envelope at this point"); - uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Max:", 192, cy, 100, 20, &fed->max, -UI_FLT_MAX, UI_FLT_MAX, 10, 2, "Maximum bound of envelope at this point"); + uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Min:", 0, 0, 100, 20, &fed->min, -UI_FLT_MAX, UI_FLT_MAX, 10, 2, "Minimum bound of envelope at this point"); + uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Max:", 0, 0, 100, 20, &fed->max, -UI_FLT_MAX, UI_FLT_MAX, 10, 2, "Maximum bound of envelope at this point"); - but= uiDefIconBut(block, BUT, B_FMODIFIER_REDRAW, ICON_X, 292, cy, 18, 20, NULL, 0.0, 0.0, 0.0, 0.0, "Delete envelope control point"); + but= uiDefIconBut(block, BUT, B_FMODIFIER_REDRAW, ICON_X, 0, 0, 18, 20, NULL, 0.0, 0.0, 0.0, 0.0, "Delete envelope control point"); uiButSetFunc(but, fmod_envelope_deletepoint_cb, env, SET_INT_IN_POINTER(i)); uiBlockBeginAlign(block); - cy -= 25; } -#endif } /* --------------- */ From e55d90b340d15944d53414419d8f4671f435af75 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 2 Jul 2009 23:36:16 +0000 Subject: [PATCH 082/114] NLA SoC: Added buttons for animating NLA-Strip Influence/Speed These buttons are found in the Evaluation panel, but are currently disabled as I've yet to add the proper code to ensure that animating these will work correctly. They will hopefully be working before the end of the day. --- source/blender/editors/animation/fmodifier_ui.c | 4 ++-- source/blender/editors/space_nla/nla_buttons.c | 15 ++++++++++----- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/source/blender/editors/animation/fmodifier_ui.c b/source/blender/editors/animation/fmodifier_ui.c index 3be96031526..cd0a00fa859 100644 --- a/source/blender/editors/animation/fmodifier_ui.c +++ b/source/blender/editors/animation/fmodifier_ui.c @@ -215,7 +215,7 @@ static void draw_modifier__generator(uiLayout *layout, FModifier *fcm, short wid /* draw controls for each pair of coefficients */ row= uiLayoutRow(layout, 1); block= uiLayoutGetBlock(row); - uiDefBut(block, LABEL, 1, "y = ", 0, 0, 50, 20, NULL, 0.0, 0.0, 0, 0, ""); + uiDefBut(block, LABEL, 1, "y=", 0, 0, 50, 20, NULL, 0.0, 0.0, 0, 0, ""); cp= data->coefficients; for (i=0; (i < data->poly_order) && (cp); i++, cp+=2) { @@ -225,7 +225,7 @@ static void draw_modifier__generator(uiLayout *layout, FModifier *fcm, short wid /* coefficients */ uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 0, 0, 100, 20, cp, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "Coefficient of x"); - uiDefBut(block, LABEL, 1, "x + ", 0, 0, 40, 20, NULL, 0.0, 0.0, 0, 0, ""); + uiDefBut(block, LABEL, 1, "x+", 0, 0, 40, 20, NULL, 0.0, 0.0, 0, 0, ""); uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 0, 0, 100, 20, cp+1, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "Second coefficient"); diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c index 67c4365ff49..7eb10866b8c 100644 --- a/source/blender/editors/space_nla/nla_buttons.c +++ b/source/blender/editors/space_nla/nla_buttons.c @@ -289,7 +289,7 @@ static void nla_panel_evaluation(const bContext *C, Panel *pa) { PointerRNA strip_ptr; uiLayout *layout= pa->layout; - //uiLayout *column, *row, *subcol; + uiLayout *column; uiBlock *block; /* check context and also validity of pointer */ @@ -299,10 +299,15 @@ static void nla_panel_evaluation(const bContext *C, Panel *pa) block= uiLayoutGetBlock(layout); uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL); - // influence - // strip_time - // animated_influence - // animated_time + column= uiLayoutColumn(layout, 1); + uiLayoutSetEnabled(column, 0); // XXX for now, don't allow user to edit + uiItemR(column, NULL, 0, &strip_ptr, "animated_influence", 0, 0, 0); + uiItemR(column, NULL, 0, &strip_ptr, "influence", 0, 0, 0); + + column= uiLayoutColumn(layout, 1); + uiLayoutSetEnabled(column, 0); // XXX for now, don't allow user to edit + uiItemR(column, NULL, 0, &strip_ptr, "animated_time", 0, 0, 0); + uiItemR(column, NULL, 0, &strip_ptr, "strip_time", 0, 0, 0); } /* F-Modifiers for active NLA-Strip */ From 28d371d1178642e17f5dfc300f1500a132ce7149 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 3 Jul 2009 01:10:46 +0000 Subject: [PATCH 083/114] NLA SoC: Assorted fixes * Made NLA Editing functions more aware of transitions. - A transition can only be added between a pair of action-clips. Previous, two transitions could be added next to each other, which has undefined behaviour - Deleting a strip with transition(s) on either side will remove the transitions too. Feedback welcome on this - The 'type' setting for NLA-Strips is no longer editable. This was dangerous as it could result in transitions with undefined behaviour (though nothing would happen). * Menus for adding F-Modifiers now only show relevant modifiers (i.e. 'Invalid' is not included in the list, and 'Cycles' doesn't need to be shown for NLA since we've got repeat) * Function Generator and Noise F-Modifiers now have complete GUI's. A few settings were missed during the porting process. * F-Modifier buttons now have their source-ID's included in the RNA Pointers used. This didn't get them animateable directly, but is a step closer. --- source/blender/blenkernel/BKE_fcurve.h | 33 +++++++++-- source/blender/blenkernel/intern/nla.c | 8 +-- .../blender/editors/animation/fmodifier_ui.c | 56 +++++++++++-------- source/blender/editors/include/ED_anim_api.h | 2 +- .../editors/space_graph/graph_buttons.c | 2 +- .../blender/editors/space_graph/graph_edit.c | 31 +++++++++- .../blender/editors/space_nla/nla_buttons.c | 2 +- source/blender/editors/space_nla/nla_edit.c | 50 ++++++++++++++++- source/blender/makesdna/DNA_anim_types.h | 2 +- source/blender/makesrna/intern/rna_nla.c | 6 +- 10 files changed, 150 insertions(+), 42 deletions(-) diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h index cfc4e9077f6..4dcb08dc0df 100644 --- a/source/blender/blenkernel/BKE_fcurve.h +++ b/source/blender/blenkernel/BKE_fcurve.h @@ -1,12 +1,33 @@ -/* Testing code for new animation system in 2.5 - * Copyright 2009, Joshua Leung +/** + * $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 + * All rights reserved. + * + * Contributor(s): Joshua Leung (full recode) + * + * ***** END GPL LICENSE BLOCK ***** */ #ifndef BKE_FCURVE_H #define BKE_FCURVE_H -//struct ListBase; - struct FCurve; struct FModifier; struct ChannelDriver; @@ -54,8 +75,8 @@ typedef struct FModifierTypeInfo { short size; /* size in bytes of the struct */ short acttype; /* eFMI_Action_Types */ short requires; /* eFMI_Requirement_Flags */ - char name[32]; /* name of modifier in interface */ - char structName[32]; /* name of struct for SDNA */ + char name[64]; /* name of modifier in interface */ + char structName[64]; /* name of struct for SDNA */ /* data management function pointers - special handling */ /* free any data that is allocated separately (optional) */ diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 14e658b3903..d554fbbabc1 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -66,7 +66,6 @@ /* Remove the given NLA strip from the NLA track it occupies, free the strip's data, * and the strip itself. */ -// TODO: with things like transitions, should these get freed too? Maybe better as a UI tool void free_nlastrip (ListBase *strips, NlaStrip *strip) { /* sanity checks */ @@ -793,6 +792,7 @@ void BKE_nla_action_pushdown (AnimData *adt) /* not first, so extend mode can only be NLASTRIP_EXTEND_HOLD_FORWARD not NLASTRIP_EXTEND_HOLD, * so that it doesn't override strips in previous tracks */ + // FIXME: this needs to be more automated, since user can rearrange strips strip->extendmode= NLASTRIP_EXTEND_HOLD_FORWARD; } } @@ -844,7 +844,7 @@ short BKE_nla_tweakmode_enter (AnimData *adt) if (strip->act == activeStrip->act) strip->flag |= NLASTRIP_FLAG_TWEAKUSER; else - strip->flag &= ~NLASTRIP_FLAG_TWEAKUSER; // XXX probably don't need to clear this... + strip->flag &= ~NLASTRIP_FLAG_TWEAKUSER; } } @@ -887,8 +887,8 @@ void BKE_nla_tweakmode_exit (AnimData *adt) // TODO: need to sync the user-strip with the new state of the action! - /* for all NLA-tracks, clear the 'disabled' flag - * for all NLA-strips, clear the 'tweak-user' flag + /* for all Tracks, clear the 'disabled' flag + * for all Strips, clear the 'tweak-user' flag */ for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) { nlt->flag &= ~NLATRACK_DISABLED; diff --git a/source/blender/editors/animation/fmodifier_ui.c b/source/blender/editors/animation/fmodifier_ui.c index cd0a00fa859..7a618f4d222 100644 --- a/source/blender/editors/animation/fmodifier_ui.c +++ b/source/blender/editors/animation/fmodifier_ui.c @@ -134,7 +134,7 @@ static void delete_fmodifier_cb (bContext *C, void *fmods_v, void *fcm_v) /* --------------- */ /* draw settings for generator modifier */ -static void draw_modifier__generator(uiLayout *layout, FModifier *fcm, short width) +static void draw_modifier__generator(uiLayout *layout, ID *id, FModifier *fcm, short width) { FMod_Generator *data= (FMod_Generator *)fcm->data; uiLayout *col, *row; @@ -143,7 +143,7 @@ static void draw_modifier__generator(uiLayout *layout, FModifier *fcm, short wid PointerRNA ptr; /* init the RNA-pointer */ - RNA_pointer_create(NULL, &RNA_FModifierFunctionGenerator, fcm, &ptr); + RNA_pointer_create(id, &RNA_FModifierFunctionGenerator, fcm, &ptr); /* basic settings (backdrop + mode selector + some padding) */ col= uiLayoutColumn(layout, 1); @@ -248,31 +248,36 @@ static void draw_modifier__generator(uiLayout *layout, FModifier *fcm, short wid /* --------------- */ /* draw settings for noise modifier */ -static void draw_modifier__fn_generator(uiLayout *layout, FModifier *fcm, short width) +static void draw_modifier__fn_generator(uiLayout *layout, ID *id, FModifier *fcm, short width) { - uiLayout *col= uiLayoutColumn(layout, 0); // no grouping for now + uiLayout *col; PointerRNA ptr; /* init the RNA-pointer */ - RNA_pointer_create(NULL, &RNA_FModifierFunctionGenerator, fcm, &ptr); + RNA_pointer_create(id, &RNA_FModifierFunctionGenerator, fcm, &ptr); /* add the settings */ - uiItemR(col, NULL, 0, &ptr, "amplitude", 0, 0, 0); - uiItemR(col, NULL, 0, &ptr, "phase_multiplier", 0, 0, 0); - uiItemR(col, NULL, 0, &ptr, "phase_offset", 0, 0, 0); - uiItemR(col, NULL, 0, &ptr, "value_offset", 0, 0, 0); + col= uiLayoutColumn(layout, 1); + uiItemR(col, "", 0, &ptr, "type", 0, 0, 0); + uiItemR(col, NULL, 0, &ptr, "additive", 0, 0, 1); + + col= uiLayoutColumn(layout, 0); // no grouping for now + uiItemR(col, NULL, 0, &ptr, "amplitude", 0, 0, 0); + uiItemR(col, NULL, 0, &ptr, "phase_multiplier", 0, 0, 0); + uiItemR(col, NULL, 0, &ptr, "phase_offset", 0, 0, 0); + uiItemR(col, NULL, 0, &ptr, "value_offset", 0, 0, 0); } /* --------------- */ /* draw settings for cycles modifier */ -static void draw_modifier__cycles(uiLayout *layout, FModifier *fcm, short width) +static void draw_modifier__cycles(uiLayout *layout, ID *id, FModifier *fcm, short width) { uiLayout *split, *col; PointerRNA ptr; /* init the RNA-pointer */ - RNA_pointer_create(NULL, &RNA_FModifierCycles, fcm, &ptr); + RNA_pointer_create(id, &RNA_FModifierCycles, fcm, &ptr); /* split into 2 columns * NOTE: the mode comboboxes shouldn't get labels, otherwise there isn't enough room @@ -295,13 +300,16 @@ static void draw_modifier__cycles(uiLayout *layout, FModifier *fcm, short width) /* --------------- */ /* draw settings for noise modifier */ -static void draw_modifier__noise(uiLayout *layout, FModifier *fcm, short width) +static void draw_modifier__noise(uiLayout *layout, ID *id, FModifier *fcm, short width) { uiLayout *split, *col; PointerRNA ptr; /* init the RNA-pointer */ - RNA_pointer_create(NULL, &RNA_FModifierNoise, fcm, &ptr); + RNA_pointer_create(id, &RNA_FModifierNoise, fcm, &ptr); + + /* blending mode */ + uiItemR(layout, NULL, 0, &ptr, "modification", 0, 0, 0); /* split into 2 columns */ split= uiLayoutSplit(layout, 0.5f); @@ -479,7 +487,7 @@ static void fmod_envelope_deletepoint_cb (bContext *C, void *fcm_dv, void *ind_v } /* draw settings for envelope modifier */ -static void draw_modifier__envelope(uiLayout *layout, FModifier *fcm, short width) +static void draw_modifier__envelope(uiLayout *layout, ID *id, FModifier *fcm, short width) { FMod_Envelope *env= (FMod_Envelope *)fcm->data; FCM_EnvelopeData *fed; @@ -490,7 +498,7 @@ static void draw_modifier__envelope(uiLayout *layout, FModifier *fcm, short widt int i; /* init the RNA-pointer */ - RNA_pointer_create(NULL, &RNA_FModifierEnvelope, fcm, &ptr); + RNA_pointer_create(id, &RNA_FModifierEnvelope, fcm, &ptr); /* general settings */ col= uiLayoutColumn(layout, 1); @@ -534,13 +542,13 @@ static void draw_modifier__envelope(uiLayout *layout, FModifier *fcm, short widt /* --------------- */ /* draw settings for limits modifier */ -static void draw_modifier__limits(uiLayout *layout, FModifier *fcm, short width) +static void draw_modifier__limits(uiLayout *layout, ID *id, FModifier *fcm, short width) { uiLayout *split, *col, *row; PointerRNA ptr; /* init the RNA-pointer */ - RNA_pointer_create(NULL, &RNA_FModifierLimits, fcm, &ptr); + RNA_pointer_create(id, &RNA_FModifierLimits, fcm, &ptr); /* row 1: minimum */ { @@ -582,7 +590,7 @@ static void draw_modifier__limits(uiLayout *layout, FModifier *fcm, short width) /* --------------- */ -void ANIM_uiTemplate_fmodifier_draw (uiLayout *layout, ListBase *modifiers, FModifier *fcm) +void ANIM_uiTemplate_fmodifier_draw (uiLayout *layout, ID *id, ListBase *modifiers, FModifier *fcm) { FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); uiLayout *box, *row, *subrow; @@ -639,27 +647,27 @@ void ANIM_uiTemplate_fmodifier_draw (uiLayout *layout, ListBase *modifiers, FMod /* draw settings for individual modifiers */ switch (fcm->type) { case FMODIFIER_TYPE_GENERATOR: /* Generator */ - draw_modifier__generator(box, fcm, width); + draw_modifier__generator(box, id, fcm, width); break; case FMODIFIER_TYPE_FN_GENERATOR: /* Built-In Function Generator */ - draw_modifier__fn_generator(box, fcm, width); + draw_modifier__fn_generator(box, id, fcm, width); break; case FMODIFIER_TYPE_CYCLES: /* Cycles */ - draw_modifier__cycles(box, fcm, width); + draw_modifier__cycles(box, id, fcm, width); break; case FMODIFIER_TYPE_ENVELOPE: /* Envelope */ - draw_modifier__envelope(box, fcm, width); + draw_modifier__envelope(box, id, fcm, width); break; case FMODIFIER_TYPE_LIMITS: /* Limits */ - draw_modifier__limits(box, fcm, width); + draw_modifier__limits(box, id, fcm, width); break; case FMODIFIER_TYPE_NOISE: /* Noise */ - draw_modifier__noise(box, fcm, width); + draw_modifier__noise(box, id, fcm, width); break; default: /* unknown type */ diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index df4e704cae8..87811fa34f9 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -300,7 +300,7 @@ struct uiLayout; /* draw a given F-Modifier for some layout/UI-Block */ // XXX not quite complete yet -void ANIM_uiTemplate_fmodifier_draw(struct uiLayout *layout, ListBase *modifiers, struct FModifier *fcm); +void ANIM_uiTemplate_fmodifier_draw(struct uiLayout *layout, struct ID *id, ListBase *modifiers, struct FModifier *fcm); /* ************************************************* */ /* ASSORTED TOOLS */ diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c index 17bc78f9ee6..0e48d56ac90 100644 --- a/source/blender/editors/space_graph/graph_buttons.c +++ b/source/blender/editors/space_graph/graph_buttons.c @@ -388,7 +388,7 @@ static void graph_panel_modifiers(const bContext *C, Panel *pa) for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next) { col= uiLayoutColumn(pa->layout, 1); - ANIM_uiTemplate_fmodifier_draw(col, &fcu->modifiers, fcm); + ANIM_uiTemplate_fmodifier_draw(col, ale->id, &fcu->modifiers, fcm); } MEM_freeN(ale); diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index 9a50c5cc203..2cade676817 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -73,6 +73,7 @@ #include "BKE_report.h" #include "BKE_utildefines.h" +#include "UI_interface.h" #include "UI_view2d.h" #include "BIF_transform.h" @@ -1743,6 +1744,34 @@ void GRAPH_OT_smooth (wmOperatorType *ot) /* ******************** Add F-Modifier Operator *********************** */ +/* present a special customised popup menu for this, with some filtering */ +static int graph_fmodifier_add_invoke (bContext *C, wmOperator *op, wmEvent *event) +{ + uiPopupMenu *pup; + uiLayout *layout; + int i; + + pup= uiPupMenuBegin(C, "Add F-Curve Modifier", 0); + layout= uiPupMenuLayout(pup); + + /* start from 1 to skip the 'Invalid' modifier type */ + for (i = 1; i < FMODIFIER_NUM_TYPES; i++) { + FModifierTypeInfo *fmi= get_fmodifier_typeinfo(i); + + /* 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); + } + uiItemS(layout); + + uiPupMenuEnd(C, pup); + + return OPERATOR_CANCELLED; +} + static int graph_fmodifier_add_exec(bContext *C, wmOperator *op) { bAnimContext ac; @@ -1793,7 +1822,7 @@ void GRAPH_OT_fmodifier_add (wmOperatorType *ot) ot->idname= "GRAPH_OT_fmodifier_add"; /* api callbacks */ - ot->invoke= WM_menu_invoke; + ot->invoke= graph_fmodifier_add_invoke; ot->exec= graph_fmodifier_add_exec; ot->poll= graphop_active_fcurve_poll; diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c index 7eb10866b8c..38ac59cbc9e 100644 --- a/source/blender/editors/space_nla/nla_buttons.c +++ b/source/blender/editors/space_nla/nla_buttons.c @@ -341,7 +341,7 @@ static void nla_panel_modifiers(const bContext *C, Panel *pa) for (fcm= strip->modifiers.first; fcm; fcm= fcm->next) { col= uiLayoutColumn(pa->layout, 1); - ANIM_uiTemplate_fmodifier_draw(col, &strip->modifiers, fcm); + ANIM_uiTemplate_fmodifier_draw(col, strip_ptr.id.data, &strip->modifiers, fcm); } } diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index 9910e62b262..10b25beddff 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -386,6 +386,12 @@ static int nlaedit_add_transition_exec (bContext *C, wmOperator *op) /* check if there's space between the two */ if (IS_EQ(s1->end, s2->start)) continue; + /* make neither one is a transition + * - although this is impossible to create with the standard tools, + * the user may have altered the settings + */ + if (ELEM(NLASTRIP_TYPE_TRANSITION, s1->type, s2->type)) + continue; /* allocate new strip */ strip= MEM_callocN(sizeof(NlaStrip), "NlaStrip"); @@ -577,8 +583,18 @@ static int nlaedit_delete_exec (bContext *C, wmOperator *op) nstrip= strip->next; /* if selected, delete */ - if (strip->flag & NLASTRIP_FLAG_SELECT) + if (strip->flag & NLASTRIP_FLAG_SELECT) { + /* if a strip either side of this was a transition, delete those too */ + if ((strip->prev) && (strip->prev->type == NLASTRIP_TYPE_TRANSITION)) + free_nlastrip(&nlt->strips, strip->prev); + if ((nstrip) && (nstrip->type == NLASTRIP_TYPE_TRANSITION)) { + nstrip= nstrip->next; + free_nlastrip(&nlt->strips, strip->next); + } + + /* finally, delete this strip */ free_nlastrip(&nlt->strips, strip); + } } } @@ -1026,6 +1042,36 @@ void NLA_OT_clear_scale (wmOperatorType *ot) /* ******************** Add F-Modifier Operator *********************** */ +/* present a special customised popup menu for this, with some filtering */ +static int nla_fmodifier_add_invoke (bContext *C, wmOperator *op, wmEvent *event) +{ + uiPopupMenu *pup; + uiLayout *layout; + int i; + + pup= uiPupMenuBegin(C, "Add F-Modifier", 0); + layout= uiPupMenuLayout(pup); + + /* start from 1 to skip the 'Invalid' modifier type */ + for (i = 1; i < FMODIFIER_NUM_TYPES; i++) { + FModifierTypeInfo *fmi= get_fmodifier_typeinfo(i); + + /* check if modifier is valid for this context */ + if (fmi == NULL) + continue; + if (i == FMODIFIER_TYPE_CYCLES) /* we already have repeat... */ + continue; + + /* add entry to add this type of modifier */ + uiItemEnumO(layout, fmi->name, 0, "NLA_OT_fmodifier_add", "type", i); + } + uiItemS(layout); + + uiPupMenuEnd(C, pup); + + return OPERATOR_CANCELLED; +} + static int nla_fmodifier_add_exec(bContext *C, wmOperator *op) { bAnimContext ac; @@ -1089,7 +1135,7 @@ void NLA_OT_fmodifier_add (wmOperatorType *ot) ot->idname= "NLA_OT_fmodifier_add"; /* api callbacks */ - ot->invoke= WM_menu_invoke; + ot->invoke= nla_fmodifier_add_invoke; ot->exec= nla_fmodifier_add_exec; ot->poll= nlaop_poll_tweakmode_off; diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h index ad3edde6552..f9508efef31 100644 --- a/source/blender/makesdna/DNA_anim_types.h +++ b/source/blender/makesdna/DNA_anim_types.h @@ -69,7 +69,7 @@ enum { FMODIFIER_TYPE_FN_GENERATOR, FMODIFIER_TYPE_ENVELOPE, FMODIFIER_TYPE_CYCLES, - FMODIFIER_TYPE_NOISE, /* unimplemented - generate variations using some basic noise generator... */ + FMODIFIER_TYPE_NOISE, FMODIFIER_TYPE_FILTER, /* unimplemented - for applying: fft, high/low pass filters, etc. */ FMODIFIER_TYPE_PYTHON, FMODIFIER_TYPE_LIMITS, diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c index 965692212a5..dfa496fd8f3 100644 --- a/source/blender/makesrna/intern/rna_nla.c +++ b/source/blender/makesrna/intern/rna_nla.c @@ -228,6 +228,7 @@ void rna_def_nlastrip(BlenderRNA *brna) /* Enums */ prop= RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "type"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); // XXX for now, not editable, since this is dangerous RNA_def_property_enum_items(prop, prop_type_items); RNA_def_property_ui_text(prop, "Type", "Type of NLA Strip."); @@ -296,7 +297,10 @@ void rna_def_nlastrip(BlenderRNA *brna) RNA_def_property_range(prop, 0.0001f, 1000.0f); /* these limits can be extended, but beyond this, we can get some crazy+annoying bugs due to numeric errors */ RNA_def_property_ui_text(prop, "Scale", "Scaling factor for action."); - // TODO: strip's F-Curves? + /* Strip's F-Curves */ + prop= RNA_def_property(srna, "fcurves", PROP_COLLECTION, PROP_NONE); + RNA_def_property_struct_type(prop, "FCurve"); + RNA_def_property_ui_text(prop, "F-Curves", "F-Curves for controlling the strip's influence and timing."); /* Strip's F-Modifiers */ prop= RNA_def_property(srna, "modifiers", PROP_COLLECTION, PROP_NONE); From a07d1ea3ea1875f938327d37fbb219717e325ada Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 3 Jul 2009 04:24:19 +0000 Subject: [PATCH 084/114] NLA SoC: Quick hack to get layer buttons in 3D view updating visible layers correctly. Now it is possible to load old files and be able to switch layers to show/hide objects AND have that reflected in the Animation Editors which rely on the scene layers being set correctly. --- .../editors/space_view3d/view3d_header.c | 28 +++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c index 5edcd203e16..605f6d6b02f 100644 --- a/source/blender/editors/space_view3d/view3d_header.c +++ b/source/blender/editors/space_view3d/view3d_header.c @@ -117,8 +117,7 @@ #define TEST_EDITMESH if(obedit==0) return; \ if( (v3d->lay & obedit->lay)==0 ) return; -/* XXX port over */ -static void handle_view3d_lock(void) {} +/* XXX port over */ static void countall(void) {} extern void borderselect(); static int retopo_mesh_paint_check() {return 0;} @@ -201,6 +200,25 @@ static RegionView3D *wm_region_view3d(const bContext *C) return NULL; } +// XXX quickly ported across +static void handle_view3d_lock(bContext *C) +{ + Scene *scene= CTX_data_scene(C); + ScrArea *sa= CTX_wm_area(C); + View3D *v3d= (View3D *)CTX_wm_space_data(C); + + if (v3d != NULL && sa != NULL) { + if(v3d->localview==0 && v3d->scenelock && sa->spacetype==SPACE_VIEW3D) { + + /* copy to scene */ + scene->lay= v3d->lay; + scene->camera= v3d->camera; + + //copy_view3d_lock(REDRAW); + } + } +} + /* XXX; all this context stuff... should become operator */ void do_layer_buttons(bContext *C, short event) { @@ -230,7 +248,7 @@ void do_layer_buttons(bContext *C, short event) v3d->lay= (1<<20)-1; } - if(v3d->scenelock) handle_view3d_lock(); + if(v3d->scenelock) handle_view3d_lock(C); /* new layers might need unflushed events events */ DAG_scene_update_flags(scene, v3d->lay); /* tags all that moves and flushes */ @@ -266,7 +284,7 @@ static int layers_exec(bContext *C, wmOperator *op) else v3d->lay = (1<scenelock) handle_view3d_lock(); + if(v3d->scenelock) handle_view3d_lock(C); /* new layers might need unflushed events events */ DAG_scene_update_flags(scene, v3d->lay); /* tags all that moves and flushes */ @@ -5106,7 +5124,7 @@ static void do_view3d_header_buttons(bContext *C, void *arg, int event) v3d->layact= v3d->lay; } - if(v3d->scenelock) handle_view3d_lock(); + if(v3d->scenelock) handle_view3d_lock(C); ED_area_tag_redraw(sa); countall(); From 66efea5e2d94ec7296efbe03ddeb7c6c4878c9ab Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 3 Jul 2009 04:48:44 +0000 Subject: [PATCH 085/114] NLA SoC: Toggle for 'Editing in Place' The 'pin' icon beside the name of the active Action when tweaking some strip's action can be used to toggle between editing the Action's keyframes in 'mapped' time or in 'un-mapped' time. --- source/blender/blenkernel/intern/nla.c | 3 ++- source/blender/editors/space_nla/nla_channels.c | 7 +++++-- source/blender/editors/space_nla/nla_draw.c | 13 ++++++++++++- source/blender/makesdna/DNA_anim_types.h | 2 ++ 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index d554fbbabc1..1244b2900fd 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -458,8 +458,9 @@ float BKE_nla_tweakedit_remap (AnimData *adt, float cframe, short mode) /* sanity checks * - obviously we've got to have some starting data * - when not in tweakmode, the active Action does not have any scaling applied :) + * - when in tweakmode, if the no-mapping flag is set, do not map */ - if ((adt == NULL) || (adt->flag & ADT_NLA_EDIT_ON)==0) + if ((adt == NULL) || (adt->flag & ADT_NLA_EDIT_ON)==0 || (adt->flag & ADT_NLA_EDIT_NOMAP)) return cframe; /* if the active-strip info has been stored already, access this, otherwise look this up diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c index 0a2c32b5f52..5a891a541cb 100644 --- a/source/blender/editors/space_nla/nla_channels.c +++ b/source/blender/editors/space_nla/nla_channels.c @@ -264,14 +264,17 @@ static void mouse_nla_channels (bAnimContext *ac, float x, int channel_index, sh { AnimData *adt= BKE_animdata_from_id(ale->owner); /* this won't crash, right? */ - /* for now, only do something if user clicks on the 'push-down' button */ if (x >= (NLACHANNEL_NAMEWIDTH-NLACHANNEL_BUTTON_WIDTH)) { - /* activate push-down function - only usable when not in TweakMode */ if (nlaedit_is_tweakmode_on(ac) == 0) { + /* 'push-down' action - only usable when not in TweakMode */ // TODO: make this use the operator instead of calling the function directly // however, calling the operator requires that we supply the args, and that works with proper buttons only BKE_nla_action_pushdown(adt); } + else { + /* when in tweakmode, this button becomes the toggle for mapped editing */ + adt->flag ^= ADT_NLA_EDIT_NOMAP; + } } } break; diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index 6d4f65fe249..ab33434077e 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -886,7 +886,18 @@ void draw_nla_channel_list (bAnimContext *ac, SpaceNla *snla, ARegion *ar) /* now draw some indicator icons */ if ((adt) && (adt->flag & ADT_NLA_EDIT_ON)) { - /* 'tweaking action' - not a button */ + /* toggle for tweaking with mapping/no-mapping (i.e. 'in place editing' toggle) */ + // for now, use pin icon to symbolise this + if (adt->flag & ADT_NLA_EDIT_NOMAP) + UI_icon_draw((float)(NLACHANNEL_NAMEWIDTH-offset), ydatac, ICON_PINNED); + else + UI_icon_draw((float)(NLACHANNEL_NAMEWIDTH-offset), ydatac, ICON_UNPINNED); + + fdrawline((float)(NLACHANNEL_NAMEWIDTH-offset), yminc, + (float)(NLACHANNEL_NAMEWIDTH-offset), ymaxc); + offset += 16;; + + /* 'tweaking action' indicator - not a button */ UI_icon_draw((float)NLACHANNEL_NAMEWIDTH-offset, ydatac, ICON_EDIT); } else { diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h index f9508efef31..110b33850f0 100644 --- a/source/blender/makesdna/DNA_anim_types.h +++ b/source/blender/makesdna/DNA_anim_types.h @@ -730,6 +730,8 @@ enum { ADT_NLA_EVAL_OFF = (1<<1), /* NLA is being 'tweaked' (i.e. in EditMode) */ ADT_NLA_EDIT_ON = (1<<2), + /* active Action for 'tweaking' does not have mapping applied for editing */ + ADT_NLA_EDIT_NOMAP = (1<<3), /* drivers expanded in UI */ ADT_DRIVERS_COLLAPSED = (1<<10), From b8042f535c43c371d6bdb2fe44d0560d5802083c Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 3 Jul 2009 10:28:10 +0000 Subject: [PATCH 086/114] NLA SoC: Muting and Graph-Editor Curve visibility for (Action) Groups Groups (the Action variety) can now be muted, and also be set to not be drawn in the Graph Editor. These settings get applied to all the F-Curves within the group, overriding any settings individual F-Curves might have, allowing users to quickly mute or hide groups of curves without having to go through clicking on all of them. Also, added a flag that can be used to set the curve visiblity on AnimData level too. This will be enabled in a future commit. --- source/blender/blenkernel/intern/anim_sys.c | 19 ++++++--- .../blender/editors/animation/anim_channels.c | 14 +++++++ .../blender/editors/animation/anim_filter.c | 39 +++++++++++-------- .../editors/space_action/action_draw.c | 5 +++ .../blender/editors/space_graph/graph_draw.c | 11 ++++++ source/blender/makesdna/DNA_action_types.h | 8 ++++ source/blender/makesdna/DNA_anim_types.h | 3 ++ 7 files changed, 77 insertions(+), 22 deletions(-) diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 4c0c30fe5c1..9befe9dc9cb 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -492,11 +492,14 @@ static void animsys_evaluate_fcurves (PointerRNA *ptr, ListBase *list, AnimMappe /* calculate then execute each curve */ for (fcu= list->first; fcu; fcu= fcu->next) { - /* check if this curve should be skipped */ - if ((fcu->flag & (FCURVE_MUTED|FCURVE_DISABLED)) == 0) - { - calculate_fcurve(fcu, ctime); - animsys_execute_fcurve(ptr, remap, fcu); + /* check if this F-Curve doesn't belong to a muted group */ + if ((fcu->grp == NULL) || (fcu->grp->flag & AGRP_MUTED)==0) { + /* check if this curve should be skipped */ + if ((fcu->flag & (FCURVE_MUTED|FCURVE_DISABLED)) == 0) + { + calculate_fcurve(fcu, ctime); + animsys_execute_fcurve(ptr, remap, fcu); + } } } } @@ -551,6 +554,10 @@ void animsys_evaluate_action_group (PointerRNA *ptr, bAction *act, bActionGroup if ELEM(NULL, act, agrp) return; if ((remap) && (remap->target != act)) remap= NULL; + /* if group is muted, don't evaluated any of the F-Curve */ + if (agrp->flag & AGRP_MUTED) + return; + /* calculate then execute each curve */ for (fcu= agrp->channels.first; (fcu) && (fcu->grp == agrp); fcu= fcu->next) { @@ -884,6 +891,8 @@ static void nlastrip_evaluate_actionclip (PointerRNA *ptr, ListBase *channels, N /* check if this curve should be skipped */ if (fcu->flag & (FCURVE_MUTED|FCURVE_DISABLED)) continue; + if ((fcu->grp) && (fcu->grp->flag & AGRP_MUTED)) + continue; /* evaluate the F-Curve's value for the time given in the strip * NOTE: we use the modified time here, since strip's F-Curve Modifiers are applied on top of this diff --git a/source/blender/editors/animation/anim_channels.c b/source/blender/editors/animation/anim_channels.c index 4ac1648361e..5e9abd42aeb 100644 --- a/source/blender/editors/animation/anim_channels.c +++ b/source/blender/editors/animation/anim_channels.c @@ -928,6 +928,12 @@ static void setflag_anim_channels (bAnimContext *ac, short setting, short mode, case ACHANNEL_SETTING_EXPAND: ACHANNEL_SET_FLAG(agrp, mode, AGRP_EXPANDED); break; + case ACHANNEL_SETTING_MUTE: + ACHANNEL_SET_FLAG(agrp, mode, AGRP_MUTED); + break; + case ACHANNEL_SETTING_VISIBLE: + ACHANNEL_SET_FLAG_NEG(agrp, mode, AGRP_NOTVISIBLE); + break; } } break; @@ -1491,10 +1497,18 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s /* toggle expand */ agrp->flag ^= AGRP_EXPANDED; } + else if ((x < (offset+32)) && (ac->spacetype==SPACE_IPO)) { + /* toggle visibility (of grouped F-Curves in Graph editor) */ + agrp->flag ^= AGRP_NOTVISIBLE; + } else if (x >= (ACHANNEL_NAMEWIDTH-ACHANNEL_BUTTON_WIDTH)) { /* toggle protection/locking */ agrp->flag ^= AGRP_PROTECTED; } + else if (x >= (ACHANNEL_NAMEWIDTH-2*ACHANNEL_BUTTON_WIDTH)) { + /* toggle mute */ + agrp->flag ^= AGRP_MUTED; + } else { /* select/deselect group */ if (selectmode == SELECT_INVERT) { diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index f9c1b1bb42f..42943475a57 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -682,25 +682,30 @@ static int animdata_filter_action (ListBase *anim_data, bAction *act, int filter * cases when we should include F-Curves inside group: * - we don't care about visibility * - group is expanded - * - we're interested in keyframes, but not if they appear in selected channels + * - we just need the F-Curves present */ - // XXX what was the selection check here for again? - if ( (!(filter_mode & ANIMFILTER_VISIBLE) || EXPANDED_AGRP(agrp)) || - ( /*ANIMCHANNEL_SELOK(SEL_AGRP(agrp)) &&*/ (filter_mode & ANIMFILTER_CURVESONLY) ) ) + if ( (!(filter_mode & ANIMFILTER_VISIBLE) || EXPANDED_AGRP(agrp)) || (filter_mode & ANIMFILTER_CURVESONLY) ) { - if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_AGRP(agrp)) { - // XXX the 'owner' info here needs review... - items += animdata_filter_fcurves(anim_data, agrp->channels.first, agrp, owner, ownertype, filter_mode, owner_id); - - /* remove group from filtered list if last element is group - * (i.e. only if group had channels, which were all hidden) - */ - // XXX this is really hacky... it should be fixed in a much more elegant way! - if ( (ale) && (anim_data->last == ale) && - (ale->data == agrp) && (agrp->channels.first) ) - { - BLI_freelinkN(anim_data, ale); - items--; + /* for the Graph Editor, curves may be set to not be visible in the view to lessen clutter, + * but to do this, we need to check that the group doesn't have it's not-visible flag set preventing + * all its sub-curves to be shown + */ + if ( !(filter_mode & ANIMFILTER_CURVEVISIBLE) || !(agrp->flag & AGRP_NOTVISIBLE) ) + { + if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_AGRP(agrp)) { + // XXX the 'owner' info here needs review... + items += animdata_filter_fcurves(anim_data, agrp->channels.first, agrp, owner, ownertype, filter_mode, owner_id); + + /* remove group from filtered list if last element is group + * (i.e. only if group had channels, which were all hidden) + */ + // XXX this is really hacky... it should be fixed in a much more elegant way! + if ( (ale) && (anim_data->last == ale) && + (ale->data == agrp) && (agrp->channels.first) ) + { + BLI_freelinkN(anim_data, ale); + items--; + } } } } diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c index f3a0dda4ce7..910b9733bc8 100644 --- a/source/blender/editors/space_action/action_draw.c +++ b/source/blender/editors/space_action/action_draw.c @@ -645,6 +645,11 @@ void draw_channel_names(bAnimContext *ac, SpaceAction *saction, ARegion *ar) expand = ICON_TRIA_RIGHT; } + if (agrp->flag & AGRP_MUTED) + mute = ICON_MUTE_IPO_ON; + else + mute = ICON_MUTE_IPO_OFF; + if (EDITABLE_AGRP(agrp)) protect = ICON_UNLOCKED; else diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c index 0d7dafe2938..f8f613223db 100644 --- a/source/blender/editors/space_graph/graph_draw.c +++ b/source/blender/editors/space_graph/graph_draw.c @@ -1166,6 +1166,17 @@ void graph_draw_channel_names(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar) expand = ICON_TRIA_RIGHT; } + /* for now, 'special' (i.e. in front of name) is used to show visibility status */ + if (agrp->flag & AGRP_NOTVISIBLE) + special= ICON_CHECKBOX_DEHLT; + else + special= ICON_CHECKBOX_HLT; + + if (agrp->flag & AGRP_MUTED) + mute = ICON_MUTE_IPO_ON; + else + mute = ICON_MUTE_IPO_OFF; + if (EDITABLE_AGRP(agrp)) protect = ICON_UNLOCKED; else diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index a566f733978..4eddebc5b67 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -225,10 +225,18 @@ typedef struct bActionGroup { /* Action Group flags */ typedef enum eActionGroup_Flag { + /* group is selected */ AGRP_SELECTED = (1<<0), + /* group is 'active' / last selected one */ AGRP_ACTIVE = (1<<1), + /* keyframes/channels belonging to it cannot be edited */ AGRP_PROTECTED = (1<<2), + /* for UI, sub-channels are shown */ AGRP_EXPANDED = (1<<3), + /* sub-channels are not evaluated */ + AGRP_MUTED = (1<<4), + /* sub-channels are not visible in Graph Editor */ + AGRP_NOTVISIBLE = (1<<5), AGRP_TEMP = (1<<30), AGRP_MOVED = (1<<31) diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h index 110b33850f0..a90fad983c4 100644 --- a/source/blender/makesdna/DNA_anim_types.h +++ b/source/blender/makesdna/DNA_anim_types.h @@ -737,6 +737,9 @@ enum { ADT_DRIVERS_COLLAPSED = (1<<10), /* don't execute drivers */ ADT_DRIVERS_DISABLED = (1<<11), + + /* F-Curves from this AnimData block are not visible in the Graph Editor */ + ADT_CURVES_NOT_VISIBLE = (1<<16), } eAnimData_Flag; /* Animation Data recalculation settings (to be set by depsgraph) */ From f87fcde686c85820c510c5c7806f6b6b8466ba5c Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Mon, 6 Jul 2009 03:44:44 +0000 Subject: [PATCH 087/114] NLA SoC: Start of 'Meta' Strips Refactored the backend code/API's to support 'meta' strips (i.e. strips containing other strips). These have been implemented to be nested to 'unlimited' depths (in terms of common usages that is, though there is a very remote chance of stack-overflow in theoretrical evil cases only that shouldn't ever be encountered in production). This paves the way for implementing the necessary tweaks needed for the transform code (in addition to some cool user-level tricks) --- source/blender/blenkernel/BKE_nla.h | 8 + source/blender/blenkernel/intern/anim_sys.c | 47 +++- source/blender/blenkernel/intern/nla.c | 213 ++++++++++++------ source/blender/blenloader/intern/readfile.c | 77 +++++-- source/blender/blenloader/intern/writefile.c | 30 ++- source/blender/editors/space_nla/nla_edit.c | 120 +++++++++- source/blender/editors/space_nla/nla_intern.h | 11 + source/blender/makesdna/DNA_anim_types.h | 9 + 8 files changed, 386 insertions(+), 129 deletions(-) diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index e2b1dd89deb..efa0591bd53 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -53,6 +53,13 @@ struct NlaStrip *add_nlastrip_to_stack(struct AnimData *adt, struct bAction *act /* ----------------------------- */ /* API */ +short BKE_nlastrips_has_space(ListBase *strips, float start, float end); +void BKE_nlastrips_sort_strips(ListBase *strips); + +short BKE_nlastrips_add_strip(ListBase *strips, struct NlaStrip *strip); + +/* ............ */ + struct NlaTrack *BKE_nlatrack_find_active(ListBase *tracks); void BKE_nlatrack_set_active(ListBase *tracks, struct NlaTrack *nlt); @@ -63,6 +70,7 @@ void BKE_nlatrack_sort_strips(struct NlaTrack *nlt); short BKE_nlatrack_add_strip(struct NlaTrack *nlt, struct NlaStrip *strip); +/* ............ */ struct NlaStrip *BKE_nlastrip_find_active(struct NlaTrack *nlt); short BKE_nlastrip_within_bounds(struct NlaStrip *strip, float min, float max); diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 9befe9dc9cb..1d10744ac80 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -628,15 +628,13 @@ static void nlastrip_evaluate_controls (NlaStrip *strip, float ctime) } -/* gets the strip active at the current time for a track for evaluation purposes */ -static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index, float ctime) +/* gets the strip active at the current time for a given list of strips */ +static NlaStrip *ctime_get_strip (ListBase *strips, short *side, float ctime) { NlaStrip *strip, *estrip=NULL; - NlaEvalStrip *nes; - short side= 0; /* loop over strips, checking if they fall within the range */ - for (strip= nlt->strips.first; strip; strip= strip->next) { + for (strip= strips->first; strip; strip= strip->next) { /* check if current time occurs within this strip */ if (IN_RANGE_INCL(ctime, strip->start, strip->end)) { /* this strip is active, so try to use it */ @@ -647,13 +645,13 @@ static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index /* if time occurred before current strip... */ if (ctime < strip->start) { - if (strip == nlt->strips.first) { + if (strip == strips->first) { /* before first strip - only try to use it if it extends backwards in time too */ if (strip->extendmode == NLASTRIP_EXTEND_HOLD) estrip= strip; /* side is 'before' regardless of whether there's a useful strip */ - side= NES_TIME_BEFORE; + *side= NES_TIME_BEFORE; } else { /* before next strip - previous strip has ended, but next hasn't begun, @@ -665,7 +663,7 @@ static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index if (strip->extendmode != NLASTRIP_EXTEND_NOTHING) estrip= strip; - side= NES_TIME_AFTER; + *side= NES_TIME_AFTER; } break; } @@ -673,11 +671,11 @@ static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index /* if time occurred after current strip... */ if (ctime > strip->end) { /* only if this is the last strip should we do anything, and only if that is being held */ - if (strip == nlt->strips.last) { + if (strip == strips->last) { if (strip->extendmode != NLASTRIP_EXTEND_NOTHING) estrip= strip; - side= NES_TIME_AFTER; + *side= NES_TIME_AFTER; break; } @@ -685,6 +683,35 @@ static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index } } + /* return the matching strip found */ + return estrip; +} + +/* gets the strip active at the current time for a track for evaluation purposes */ +static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index, float ctime) +{ + ListBase *strips= &nlt->strips; + NlaStrip *strip, *estrip=NULL; + NlaEvalStrip *nes; + short side= 0; + + /* keep looping over hierarchy of strips until one which fits for the current time is found */ + while (strips->first) { + /* try to get the strip at this frame for this strip */ + strip= ctime_get_strip(strips, &side, ctime); + + /* if a strip was found, make this the new estrip, otherwise, stop trying */ + if (strip) { + /* set new estrip */ + estrip= strip; + + /* check children (only available if this is a meta-strip) for better match */ + strips= &strip->strips; + } + else + break; + } + /* check if a valid strip was found * - must not be muted (i.e. will have contribution */ diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 1244b2900fd..d01fa2c1965 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -68,10 +68,18 @@ */ void free_nlastrip (ListBase *strips, NlaStrip *strip) { + NlaStrip *cs, *csn; + /* sanity checks */ if (strip == NULL) return; + /* free child-strips */ + for (cs= strip->strips.first; cs; cs= csn) { + csn= cs->next; + free_nlastrip(&strip->strips, cs); + } + /* remove reference to action */ if (strip->act) strip->act->id.us--; @@ -144,6 +152,7 @@ void free_nladata (ListBase *tracks) NlaStrip *copy_nlastrip (NlaStrip *strip) { NlaStrip *strip_d; + NlaStrip *cs, *cs_d; /* sanity check */ if (strip == NULL) @@ -161,6 +170,14 @@ NlaStrip *copy_nlastrip (NlaStrip *strip) copy_fcurves(&strip_d->fcurves, &strip->fcurves); copy_fmodifiers(&strip_d->modifiers, &strip->modifiers); + /* make a copy of all the child-strips, one at a time */ + strip_d->strips.first= strip_d->strips.last= NULL; + + for (cs= strip->strips.first; cs; cs= cs->next) { + cs_d= copy_nlastrip(cs); + BLI_addtail(&strip_d->strips, cs_d); + } + /* return the strip */ return strip_d; } @@ -435,6 +452,7 @@ static float nlastrip_get_frame_transition (NlaStrip *strip, float cframe, short float nlastrip_get_frame (NlaStrip *strip, float cframe, short mode) { switch (strip->type) { + case NLASTRIP_TYPE_META: /* meta (is just a container for other strips, so shouldn't use the action-clip method) */ case NLASTRIP_TYPE_TRANSITION: /* transition */ return nlastrip_get_frame_transition(strip, cframe, mode); @@ -487,6 +505,117 @@ float BKE_nla_tweakedit_remap (AnimData *adt, float cframe, short mode) /* *************************************************** */ /* Basic Utilities */ +/* List of Strips ------------------------------------ */ +/* (these functions are used for NLA-Tracks and also for nested/meta-strips) */ + +/* Check if there is any space in the given list to add the given strip */ +short BKE_nlastrips_has_space (ListBase *strips, float start, float end) +{ + NlaStrip *strip; + + /* sanity checks */ + if ((strips == NULL) || IS_EQ(start, end)) + return 0; + if (start > end) { + puts("BKE_nlastrips_has_space() error... start and end arguments swapped"); + SWAP(float, start, end); + } + + /* loop over NLA strips checking for any overlaps with this area... */ + for (strip= strips->first; strip; strip= strip->next) { + /* if start frame of strip is past the target end-frame, that means that + * we've gone past the window we need to check for, so things are fine + */ + if (strip->start > end) + return 1; + + /* if the end of the strip is greater than either of the boundaries, the range + * must fall within the extents of the strip + */ + if ((strip->end > start) || (strip->end > end)) + return 0; + } + + /* if we are still here, we haven't encountered any overlapping strips */ + return 1; +} + +/* Rearrange the strips in the track so that they are always in order + * (usually only needed after a strip has been moved) + */ +void BKE_nlastrips_sort_strips (ListBase *strips) +{ + ListBase tmp = {NULL, NULL}; + NlaStrip *strip, *sstrip; + + /* sanity checks */ + if ELEM(NULL, strips, strips->first) + return; + + /* we simply perform insertion sort on this list, since it is assumed that per track, + * there are only likely to be at most 5-10 strips + */ + for (strip= strips->first; strip; strip= strip->next) { + short not_added = 1; + + /* remove this strip from the list, and add it to the new list, searching from the end of + * the list, assuming that the lists are in order + */ + BLI_remlink(strips, strip); + + for (sstrip= tmp.last; not_added && sstrip; sstrip= sstrip->prev) { + /* check if add after */ + if (sstrip->end < strip->start) { + BLI_insertlinkafter(&tmp, sstrip, strip); + not_added= 0; + break; + } + } + + /* add before first? */ + if (not_added) + BLI_addhead(&tmp, strip); + } + + /* reassign the start and end points of the strips */ + strips->first= tmp.first; + strips->last= tmp.last; +} + +/* Add the given NLA-Strip to the given list of strips, assuming that it + * isn't currently a member of another list + */ +short BKE_nlastrips_add_strip (ListBase *strips, NlaStrip *strip) +{ + NlaStrip *ns; + short not_added = 1; + + /* sanity checks */ + if ELEM(NULL, strips, strip) + return 0; + + /* check if any space to add */ + if (BKE_nlastrips_has_space(strips, strip->start, strip->end)==0) + return 0; + + /* find the right place to add the strip to the nominated track */ + for (ns= strips->first; ns; ns= ns->next) { + /* if current strip occurs after the new strip, add it before */ + if (ns->start > strip->end) { + BLI_insertlinkbefore(strips, ns, strip); + not_added= 0; + break; + } + } + if (not_added) { + /* just add to the end of the list of the strips then... */ + BLI_addtail(strips, strip); + } + + /* added... */ + return 1; +} + /* NLA-Tracks ---------------------------------------- */ /* Find the active NLA-track for the given stack */ @@ -560,36 +689,20 @@ void BKE_nlatrack_set_active (ListBase *tracks, NlaTrack *nlt_a) nlt_a->flag |= NLATRACK_ACTIVE; } -/* Check if there is any space in the last track to add the given strip */ + +/* Check if there is any space in the given track to add a strip of the given length */ short BKE_nlatrack_has_space (NlaTrack *nlt, float start, float end) { - NlaStrip *strip; - /* sanity checks */ if ((nlt == NULL) || IS_EQ(start, end)) return 0; if (start > end) { - puts("BKE_nlatrack_has_space error... start and end arguments swapped"); + puts("BKE_nlatrack_has_space() error... start and end arguments swapped"); SWAP(float, start, end); } - /* loop over NLA strips checking for any overlaps with this area... */ - for (strip= nlt->strips.first; strip; strip= strip->next) { - /* if start frame of strip is past the target end-frame, that means that - * we've gone past the window we need to check for, so things are fine - */ - if (strip->start > end) - return 1; - - /* if the end of the strip is greater than either of the boundaries, the range - * must fall within the extents of the strip - */ - if ((strip->end > start) || (strip->end > end)) - return 0; - } - - /* if we are still here, we haven't encountered any overlapping strips */ - return 1; + /* check if there's any space left in the track for a strip of the given length */ + return BKE_nlastrips_has_space(&nlt->strips, start, end); } /* Rearrange the strips in the track so that they are always in order @@ -597,41 +710,12 @@ short BKE_nlatrack_has_space (NlaTrack *nlt, float start, float end) */ void BKE_nlatrack_sort_strips (NlaTrack *nlt) { - ListBase tmp = {NULL, NULL}; - NlaStrip *strip, *sstrip; - /* sanity checks */ if ELEM(NULL, nlt, nlt->strips.first) return; - - /* we simply perform insertion sort on this list, since it is assumed that per track, - * there are only likely to be at most 5-10 strips - */ - for (strip= nlt->strips.first; strip; strip= strip->next) { - short not_added = 1; - - /* remove this strip from the list, and add it to the new list, searching from the end of - * the list, assuming that the lists are in order - */ - BLI_remlink(&nlt->strips, strip); - - for (sstrip= tmp.last; not_added && sstrip; sstrip= sstrip->prev) { - /* check if add after */ - if (sstrip->end < strip->start) { - BLI_insertlinkafter(&tmp, sstrip, strip); - not_added= 0; - break; - } - } - - /* add before first? */ - if (not_added) - BLI_addhead(&tmp, strip); - } - /* reassign the start and end points of the strips */ - nlt->strips.first= tmp.first; - nlt->strips.last= tmp.last; + /* sort the strips with a more generic function */ + BKE_nlastrips_sort_strips(&nlt->strips); } /* Add the given NLA-Strip to the given NLA-Track, assuming that it @@ -639,33 +723,12 @@ void BKE_nlatrack_sort_strips (NlaTrack *nlt) */ short BKE_nlatrack_add_strip (NlaTrack *nlt, NlaStrip *strip) { - NlaStrip *ns; - short not_added = 1; - /* sanity checks */ if ELEM(NULL, nlt, strip) return 0; - /* check if any space to add */ - if (BKE_nlatrack_has_space(nlt, strip->start, strip->end)==0) - return 0; - - /* find the right place to add the strip to the nominated track */ - for (ns= nlt->strips.first; ns; ns= ns->next) { - /* if current strip occurs after the new strip, add it before */ - if (ns->start > strip->end) { - BLI_insertlinkbefore(&nlt->strips, ns, strip); - not_added= 0; - break; - } - } - if (not_added) { - /* just add to the end of the list of the strips then... */ - BLI_addtail(&nlt->strips, strip); - } - - /* added... */ - return 1; + /* try to add the strip to the track using a more generic function */ + return BKE_nlastrips_add_strip(&nlt->strips, strip); } /* NLA Strips -------------------------------------- */ diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index beebf58b6c0..956c8e0042e 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -1826,18 +1826,48 @@ static void direct_link_action(FileData *fd, bAction *act) } } - -static void lib_link_nladata (FileData *fd, ID *id, ListBase *list) +static void lib_link_nladata_strips(FileData *fd, ID *id, ListBase *list) { - NlaTrack *nlt; NlaStrip *strip; - /* we only acare about the NLA strips inside the tracks */ + for (strip= list->first; strip; strip= strip->next) { + /* check strip's children */ + lib_link_nladata_strips(fd, id, &strip->strips); + + /* reassign the counted-reference to action */ + strip->act = newlibadr_us(fd, id->lib, strip->act); + } +} + +static void lib_link_nladata(FileData *fd, ID *id, ListBase *list) +{ + NlaTrack *nlt; + + /* we only care about the NLA strips inside the tracks */ for (nlt= list->first; nlt; nlt= nlt->next) { - for (strip= nlt->strips.first; strip; strip= strip->next) { - /* reassign the counted-reference to action */ - strip->act = newlibadr_us(fd, id->lib, strip->act); - } + lib_link_nladata_strips(fd, id, &nlt->strips); + } +} + +/* This handles Animato NLA-Strips linking + * NOTE: this assumes that link_list has already been called on the list + */ +static void direct_link_nladata_strips(FileData *fd, ListBase *list) +{ + NlaStrip *strip; + + for (strip= list->first; strip; strip= strip->next) { + /* strip's child strips */ + link_list(fd, &strip->strips); + direct_link_nladata_strips(fd, &strip->strips); + + /* strip's F-Curves */ + link_list(fd, &strip->fcurves); + direct_link_fcurves(fd, &strip->fcurves); + + /* strip's F-Modifiers */ + link_list(fd, &strip->modifiers); + direct_link_fcurves(fd, &strip->modifiers); } } @@ -1845,22 +1875,13 @@ static void lib_link_nladata (FileData *fd, ID *id, ListBase *list) static void direct_link_nladata(FileData *fd, ListBase *list) { NlaTrack *nlt; - NlaStrip *strip; for (nlt= list->first; nlt; nlt= nlt->next) { /* relink list of strips */ link_list(fd, &nlt->strips); /* relink strip data */ - for (strip= nlt->strips.first; strip; strip= strip->next) { - /* strip's F-Curves */ - link_list(fd, &strip->fcurves); - direct_link_fcurves(fd, &strip->fcurves); - - /* strip's F-Modifiers */ - link_list(fd, &strip->modifiers); - direct_link_fcurves(fd, &strip->modifiers); - } + direct_link_nladata_strips(fd, &nlt->strips); } } @@ -9560,11 +9581,23 @@ static void expand_keyingsets(FileData *fd, Main *mainvar, ListBase *list) } } +static void expand_animdata_nlastrips(FileData *fd, Main *mainvar, ListBase *list) +{ + NlaStrip *strip; + + for (strip= list->first; strip; strip= strip->next) { + /* check child strips */ + expand_animdata_nlastrips(fd, mainvar, &strip->strips); + + /* relink referenced action */ + expand_doit(fd, mainvar, strip->act); + } +} + static void expand_animdata(FileData *fd, Main *mainvar, AnimData *adt) { FCurve *fcd; NlaTrack *nlt; - NlaStrip *strip; /* own action */ expand_doit(fd, mainvar, adt->action); @@ -9580,10 +9613,8 @@ static void expand_animdata(FileData *fd, Main *mainvar, AnimData *adt) } /* nla-data - referenced actions */ - for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) { - for (strip= nlt->strips.first; strip; strip= strip->next) - expand_doit(fd, mainvar, strip->act); - } + for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) + expand_animdata_nlastrips(fd, mainvar, &nlt->strips); } static void expand_particlesettings(FileData *fd, Main *mainvar, ParticleSettings *part) diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 80d1d78257b..bfdd89e38b1 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -916,26 +916,34 @@ static void write_keyingsets(WriteData *wd, ListBase *list) } } +static void write_nlastrips(WriteData *wd, ListBase *strips) +{ + NlaStrip *strip; + + for (strip= strips->first; strip; strip= strip->next) { + /* write the strip first */ + writestruct(wd, DATA, "NlaStrip", 1, strip); + + /* write the strip's F-Curves and modifiers */ + write_fcurves(wd, &strip->fcurves); + write_fmodifiers(wd, &strip->modifiers); + + /* write the strip's children */ + write_nlastrips(wd, &strip->strips); + } +} + static void write_nladata(WriteData *wd, ListBase *nlabase) { NlaTrack *nlt; - NlaStrip *strip; /* write all the tracks */ for (nlt= nlabase->first; nlt; nlt= nlt->next) { /* write the track first */ writestruct(wd, DATA, "NlaTrack", 1, nlt); - for (strip= nlt->strips.first; strip; strip= strip->next) { - /* write the strip first */ - writestruct(wd, DATA, "NlaStrip", 1, strip); - - /* write the strip's F-Curves and modifiers */ - write_fcurves(wd, &strip->fcurves); - write_fmodifiers(wd, &strip->modifiers); - - // TODO write the remaps - } + /* write the track's strips */ + write_nlastrips(wd, &nlt->strips); } } diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index 10b25beddff..e95d0b1a50a 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -734,8 +734,6 @@ static int nlaedit_move_up_exec (bContext *C, wmOperator *op) bAnimListElem *ale; int filter; - BeztEditData bed; - /* get editor data */ if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; @@ -744,9 +742,6 @@ static int nlaedit_move_up_exec (bContext *C, wmOperator *op) filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT); ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - /* init the editing data */ - memset(&bed, 0, sizeof(BeztEditData)); - /* since we're potentially moving strips from lower tracks to higher tracks, we should * loop over the tracks in reverse order to avoid moving earlier strips up multiple tracks */ @@ -811,8 +806,6 @@ static int nlaedit_move_down_exec (bContext *C, wmOperator *op) bAnimListElem *ale; int filter; - BeztEditData bed; - /* get editor data */ if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; @@ -821,9 +814,6 @@ static int nlaedit_move_down_exec (bContext *C, wmOperator *op) filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT); ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - /* init the editing data */ - memset(&bed, 0, sizeof(BeztEditData)); - /* loop through the tracks in normal order, since we're pushing strips down, * strips won't get operated on twice */ @@ -1037,6 +1027,116 @@ void NLA_OT_clear_scale (wmOperatorType *ot) ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } +/* ******************** Snap Strips Operator ************************** */ +/* Moves the start-point of the selected strips to the specified places */ + +/* defines for snap keyframes tool */ +EnumPropertyItem prop_nlaedit_snap_types[] = { + {NLAEDIT_SNAP_CFRA, "CFRA", 0, "Current frame", ""}, + {NLAEDIT_SNAP_NEAREST_FRAME, "NEAREST_FRAME", 0, "Nearest Frame", ""}, // XXX as single entry? + {NLAEDIT_SNAP_NEAREST_SECOND, "NEAREST_SECOND", 0, "Nearest Second", ""}, // XXX as single entry? + {NLAEDIT_SNAP_NEAREST_MARKER, "NEAREST_MARKER", 0, "Nearest Marker", ""}, + {0, NULL, 0, NULL, NULL} +}; + +static int nlaedit_snap_exec (bContext *C, wmOperator *op) +{ + bAnimContext ac; + + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + Scene *scene= ac.scene; + int mode = RNA_enum_get(op->ptr, "type"); + const float secf = (float)FPS; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* get a list of the editable tracks being shown in the NLA */ + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* since we may add tracks, perform this in reverse order */ + for (ale= anim_data.last; ale; ale= ale->prev) { + ListBase tmp_strips = {NULL, NULL}; + NlaTrack *nlt= (NlaTrack *)ale->data; + NlaStrip *strip, *stripn; + + /* first pass: move all selected strips to a separate buffer, and apply snapping to them */ + for (strip= nlt->strips.first; strip; strip= stripn) { + stripn= strip->next; + + if (strip->flag & NLASTRIP_FLAG_SELECT) { + float start, end; + + /* get the existing end-points */ + start= strip->start; + end= strip->end; + + /* calculate new start position based on snapping mode */ + switch (mode) { + case NLAEDIT_SNAP_CFRA: /* to current frame */ + strip->start= (float)CFRA; + break; + case NLAEDIT_SNAP_NEAREST_FRAME: /* to nearest frame */ + strip->start= (float)(floor(start+0.5)); + break; + case NLAEDIT_SNAP_NEAREST_SECOND: /* to nearest second */ + strip->start= ((float)floor(start/secf + 0.5f) * secf); + break; + case NLAEDIT_SNAP_NEAREST_MARKER: /* to nearest marker */ + strip->start= (float)ED_markers_find_nearest_marker_time(ac.markers, start); + break; + default: /* just in case... no snapping */ + strip->start= start; + break; + } + + /* get new endpoint based on start-point (and old length) */ + strip->end= strip->start + (end - start); + + /* remove strip from track, and add to the temp buffer */ + BLI_remlink(&nlt->strips, strip); + BLI_addtail(&tmp_strips, strip); + } + } + + // TODO: finish this... + } + + /* free temp data */ + BLI_freelistN(&anim_data); + + /* set notifier that things have changed */ + ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); + WM_event_add_notifier(C, NC_SCENE, NULL); + + /* done */ + return OPERATOR_FINISHED; +} + +void NLA_OT_snap (wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Snap Strips"; + ot->idname= "NLA_OT_snap"; + ot->description= "Move start of strips to specified time."; + + /* api callbacks */ + ot->invoke= WM_menu_invoke; + ot->exec= nlaedit_snap_exec; + ot->poll= nlaop_poll_tweakmode_off; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* properties */ + RNA_def_enum(ot->srna, "type", prop_nlaedit_snap_types, 0, "Type", ""); +} + /* *********************************************** */ /* NLA Modifiers */ diff --git a/source/blender/editors/space_nla/nla_intern.h b/source/blender/editors/space_nla/nla_intern.h index 5921b8a75ce..422686bb424 100644 --- a/source/blender/editors/space_nla/nla_intern.h +++ b/source/blender/editors/space_nla/nla_intern.h @@ -87,6 +87,17 @@ void NLA_OT_click_select(wmOperatorType *ot); /* **************************************** */ /* nla_edit.c */ +/* defines for snap strips + */ +enum { + NLAEDIT_SNAP_CFRA = 1, + NLAEDIT_SNAP_NEAREST_FRAME, + NLAEDIT_SNAP_NEAREST_SECOND, + NLAEDIT_SNAP_NEAREST_MARKER, +} eNlaEdit_Snap_Mode; + +/* --- */ + void NLA_OT_tweakmode_enter(wmOperatorType *ot); void NLA_OT_tweakmode_exit(wmOperatorType *ot); diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h index a90fad983c4..a8220099a11 100644 --- a/source/blender/makesdna/DNA_anim_types.h +++ b/source/blender/makesdna/DNA_anim_types.h @@ -438,11 +438,13 @@ typedef struct AnimMapper { typedef struct NlaStrip { struct NlaStrip *next, *prev; + ListBase strips; /* 'Child' strips (used for 'meta' strips) */ bAction *act; /* Action that is referenced by this strip (strip is 'user' of the action) */ AnimMapper *remap; /* Remapping info this strip (for tweaking correspondance of action with context) */ ListBase fcurves; /* F-Curves for controlling this strip's influence and timing */ // TODO: move out? ListBase modifiers; /* F-Curve modifiers to be applied to the entire strip's referenced F-Curves */ + float influence; /* Influence of strip */ float strip_time; /* Current 'time' within action being used (automatically evaluated, but can be overridden) */ @@ -505,6 +507,11 @@ enum { NLASTRIP_FLAG_MUTED = (1<<12), /* NLA strip length is synced to the length of the referenced action */ NLASTRIP_FLAG_SYNC_LENGTH = (1<<13), + + /* temporary editing flags */ + /* NLA-Strip is really just a temporary meta used to facilitate easier transform code */ + NLASTRIP_FLAG_TEMP_META = (1<<30), + NLASTRIP_FLAG_EDIT_TOUCHED = (1<<31), } eNlaStrip_Flag; /* NLA Strip Type */ @@ -513,6 +520,8 @@ enum { NLASTRIP_TYPE_CLIP = 0, /* 'transition' - blends between the adjacent strips */ NLASTRIP_TYPE_TRANSITION, + /* 'meta' - a strip which acts as a container for a few others */ + NLASTRIP_TYPE_META, } eNlaStrip_Type; /* NLA Tracks ------------------------------------- */ From 158657026122d3b169f1bea12a69ff8eb16bbe04 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Mon, 6 Jul 2009 11:06:34 +0000 Subject: [PATCH 088/114] NLA SoC: More work on Meta-Strips * Added several API functions for Meta-Strips editing. One of these (flush transform) still needs a few tweaks before it does its job well enough for all cases. * Meta strips are now drawn with a purple-ish colour. The start/end points of the strips they encompass are shown with lines along the length of the strips, with lines starting from the top indicating start-points and lines starting from the bottom indicating end-points. * Meta strips can be made (i.e. strips can be assigned to meta-strips) by selecting some strips and pressing Shift-G. Meta strips can be removed by selecting some meta-strips and pressing Alt-G. * Strips can now be 'snapped' to start from: the current frame, the nearest frame, the nearest second, or the nearest marker; using the Shift-S hotkey. 'Islands' of adjacent selected strips occurring in the same track are moved together as a single strip so that the start-point of the first strip is on the sepcified time, but all the relative lengths of strips stay the same. Internally, temporary meta-strips are created to facilitate this. --- source/blender/blenkernel/BKE_nla.h | 6 + source/blender/blenkernel/intern/nla.c | 193 ++++++++++++++++++ source/blender/editors/space_nla/nla_draw.c | 39 +++- source/blender/editors/space_nla/nla_edit.c | 148 +++++++++++++- source/blender/editors/space_nla/nla_header.c | 16 ++ source/blender/editors/space_nla/nla_intern.h | 5 + source/blender/editors/space_nla/nla_ops.c | 12 ++ source/blender/makesdna/DNA_anim_types.h | 4 +- source/blender/makesrna/intern/rna_nla.c | 1 + 9 files changed, 415 insertions(+), 9 deletions(-) diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index efa0591bd53..3fcd799310e 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -58,6 +58,12 @@ void BKE_nlastrips_sort_strips(ListBase *strips); short BKE_nlastrips_add_strip(ListBase *strips, struct NlaStrip *strip); + +void BKE_nlastrips_make_metas(ListBase *strips, short temp); +void BKE_nlastrips_clear_metas(ListBase *strips, short onlySel, short onlyTemp); +short BKE_nlameta_add_strip(struct NlaStrip *mstrip, struct NlaStrip *strip); +void BKE_nlameta_flush_transforms(struct NlaStrip *mstrip); + /* ............ */ struct NlaTrack *BKE_nlatrack_find_active(ListBase *tracks); diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index d01fa2c1965..715f99c820f 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -616,6 +616,199 @@ short BKE_nlastrips_add_strip (ListBase *strips, NlaStrip *strip) return 1; } + +/* Meta-Strips ------------------------------------ */ + +/* Convert 'islands' (i.e. continuous string of) selected strips to be + * contained within 'Meta-Strips' which act as strips which contain strips. + * temp: are the meta-strips to be created 'temporary' ones used for transforms? + */ +void BKE_nlastrips_make_metas (ListBase *strips, short temp) +{ + NlaStrip *mstrip = NULL; + NlaStrip *strip, *stripn; + + /* sanity checks */ + if ELEM(NULL, strips, strips->first) + return; + + /* group all continuous chains of selected strips into meta-strips */ + for (strip= strips->first; strip; strip= stripn) { + stripn= strip->next; + + if (strip->flag & NLASTRIP_FLAG_SELECT) { + /* if there is an existing meta-strip, add this strip to it, otherwise, create a new one */ + if (mstrip == NULL) { + /* add a new meta-strip, and add it before the current strip that it will replace... */ + mstrip= MEM_callocN(sizeof(NlaStrip), "Meta-NlaStrip"); + mstrip->type = NLASTRIP_TYPE_META; + BLI_insertlinkbefore(strips, strip, mstrip); + + /* set flags */ + mstrip->flag = NLASTRIP_FLAG_SELECT; + + /* set temp flag if appropriate (i.e. for transform-type editing) */ + if (temp) + mstrip->flag |= NLASTRIP_FLAG_TEMP_META; + + /* make its start frame be set to the start frame of the current strip */ + mstrip->start= strip->start; + } + + /* remove the selected strips from the track, and add to the meta */ + BLI_remlink(strips, strip); + BLI_addtail(&mstrip->strips, strip); + + /* expand the meta's dimensions to include the newly added strip- i.e. its last frame */ + mstrip->end= strip->end; + } + else { + /* current strip wasn't selected, so the end of 'island' of selected strips has been reached, + * so stop adding strips to the current meta + */ + mstrip= NULL; + } + } +} + +/* Remove meta-strips (i.e. flatten the list of strips) from the top-level of the list of strips + * sel: only consider selected meta-strips, otherwise all meta-strips are removed + * onlyTemp: only remove the 'temporary' meta-strips used for transforms + */ +void BKE_nlastrips_clear_metas (ListBase *strips, short onlySel, short onlyTemp) +{ + NlaStrip *strip, *stripn; + + /* sanity checks */ + if ELEM(NULL, strips, strips->first) + return; + + /* remove meta-strips fitting the criteria of the arguments */ + for (strip= strips->first; strip; strip= stripn) { + stripn= strip->next; + + /* check if strip is a meta-strip */ + if (strip->type == NLASTRIP_TYPE_META) { + /* if check if selection and 'temporary-only' considerations are met */ + if ((onlySel==0) || (strip->flag & NLASTRIP_FLAG_SELECT)) { + if ((!onlyTemp) || (strip->flag & NLASTRIP_FLAG_TEMP_META)) { + NlaStrip *cs, *csn; + + /* move each one of the meta-strip's children before the meta-strip + * in the list of strips after unlinking them from the meta-strip + */ + for (cs= strip->strips.first; cs; cs= csn) { + csn= cs->next; + BLI_remlink(&strip->strips, cs); + BLI_insertlinkbefore(strips, strip, cs); + } + + /* free the meta-strip now */ + BLI_freelinkN(strips, strip); + } + } + } + } +} + +/* Add the given NLA-Strip to the given Meta-Strip, assuming that the + * strip isn't attached to anyy list of strips + */ +short BKE_nlameta_add_strip (NlaStrip *mstrip, NlaStrip *strip) +{ + /* sanity checks */ + if ELEM(NULL, mstrip, strip) + return 0; + + /* firstly, check if the meta-strip has space for this */ + if (BKE_nlastrips_has_space(&mstrip->strips, strip->start, strip->end) == 0) + return 0; + + /* check if this would need to be added to the ends of the meta, + * and subsequently, if the neighbouring strips allow us enough room + */ + if (strip->start < mstrip->start) { + /* check if strip to the left (if it exists) ends before the + * start of the strip we're trying to add + */ + if ((mstrip->prev == NULL) || (mstrip->prev->end <= strip->start)) { + /* add strip to start of meta's list, and expand dimensions */ + BLI_addhead(&mstrip->strips, strip); + mstrip->start= strip->start; + + return 1; + } + else /* failed... no room before */ + return 0; + } + else if (strip->end > mstrip->end) { + /* check if strip to the right (if it exists) starts before the + * end of the strip we're trying to add + */ + if ((mstrip->next == NULL) || (mstrip->next->start >= strip->end)) { + /* add strip to end of meta's list, and expand dimensions */ + BLI_addtail(&mstrip->strips, strip); + mstrip->end= strip->end; + + return 1; + } + else /* failed... no room after */ + return 0; + } + else { + /* just try to add to the meta-strip (no dimension changes needed) */ + return BKE_nlastrips_add_strip(&mstrip->strips, strip); + } +} + +/* Adjust the settings of NLA-Strips contained within a Meta-Strip (recursively), + * until the Meta-Strips children all fit within the Meta-Strip's new dimensions + */ +void BKE_nlameta_flush_transforms (NlaStrip *mstrip) +{ + NlaStrip *strip; + float oStart, oEnd, offset; + + /* sanity checks + * - strip must exist + * - strip must be a meta-strip with some contents + */ + if ELEM(NULL, mstrip, mstrip->strips.first) + return; + if (mstrip->type != NLASTRIP_TYPE_META) + return; + + /* get the original start/end points, and calculate the start-frame offset + * - these are simply the start/end frames of the child strips, + * since we assume they weren't transformed yet + */ + oStart= ((NlaStrip *)mstrip->strips.first)->start; + oEnd= ((NlaStrip *)mstrip->strips.last)->end; + offset= mstrip->start - oStart; + + /* optimisation: + * don't flush if nothing changed yet + * TODO: maybe we need a flag to say always flush? + */ + if (IS_EQ(oStart, mstrip->start) && IS_EQ(oEnd, mstrip->end)) + return; + + /* for each child-strip, calculate new start/end points based on this new info */ + for (strip= mstrip->strips.first; strip; strip= strip->next) { + //PointerRNA strip_ptr; + + /* firstly, just apply the changes in offset to both ends of the strip */ + strip->start += offset; + strip->end += offset; + + /* now, we need to fix the endpoint to take into account scaling */ + // TODO.. + + /* finally, make sure the strip's children (if it is a meta-itself), get updated */ + BKE_nlameta_flush_transforms(strip); + } +} + /* NLA-Tracks ---------------------------------------- */ /* Find the active NLA-track for the given stack */ diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index ab33434077e..e31aebf0155 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -176,6 +176,23 @@ static void nla_strip_get_color_inside (AnimData *adt, NlaStrip *strip, float co color[2]= 0.19f; } } + else if (strip->type == NLASTRIP_TYPE_META) { + /* Meta Clip */ + if (strip->flag & NLASTRIP_FLAG_SELECT) { + /* selected - use a bold purple color */ + // FIXME: hardcoded temp-hack colors + color[0]= 0.41f; + color[1]= 0.13f; + color[2]= 0.59f; + } + else { + /* normal, unselected strip - use (hardly noticable) dark purple tinge */ + // FIXME: hardcoded temp-hack colors + color[0]= 0.20f; + color[1]= 0.15f; + color[2]= 0.26f; + } + } else { /* Action Clip (default/normal type of strip) */ if ((strip->flag & NLASTRIP_FLAG_ACTIVE) && (adt && (adt->flag & ADT_NLA_EDIT_ON))) { @@ -293,7 +310,7 @@ static void nla_draw_strip (AnimData *adt, NlaTrack *nlt, NlaStrip *strip, View2 /* draw outline */ gl_round_box_shade(GL_LINE_LOOP, strip->start, yminc, strip->end, ymaxc, 0.0, 0.0, 0.1); - /* if action-clip strip, draw lines delimiting repeats too (in the same colour */ + /* if action-clip strip, draw lines delimiting repeats too (in the same color as outline) */ if ((strip->type == NLASTRIP_TYPE_CLIP) && IS_EQ(strip->repeat, 1.0f)==0) { float repeatLen = (strip->actend - strip->actstart) * strip->scale; int i; @@ -309,6 +326,26 @@ static void nla_draw_strip (AnimData *adt, NlaTrack *nlt, NlaStrip *strip, View2 fdrawline(repeatPos, yminc, repeatPos, ymaxc); } } + /* or if meta-strip, draw lines delimiting extents of sub-strips (in same color as outline, if more than 1 exists) */ + else if ((strip->type == NLASTRIP_TYPE_META) && (strip->strips.first != strip->strips.last)) { + NlaStrip *cs; + float y= (ymaxc-yminc)/2.0f + yminc; + + /* only draw first-level of child-strips, but don't draw any lines on the endpoints */ + for (cs= strip->strips.first; cs; cs= cs->next) { + /* draw start-line if not same as end of previous (and only if not the first strip) + * - on upper half of strip + */ + if ((cs->prev) && IS_EQ(cs->prev->end, cs->start)==0) + fdrawline(cs->start, y, cs->start, ymaxc); + + /* draw end-line if not the last strip + * - on lower half of strip + */ + if (cs->next) + fdrawline(cs->end, yminc, cs->end, y); + } + } /* reset linestyle */ setlinestyle(0); diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index e95d0b1a50a..f7d4db17e2c 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -346,7 +346,6 @@ void NLA_OT_add_actionclip (wmOperatorType *ot) /* ******************** Add Transition Operator ***************************** */ /* Add a new transition strip between selected strips */ -/* add the specified action as new strip */ static int nlaedit_add_transition_exec (bContext *C, wmOperator *op) { bAnimContext ac; @@ -453,6 +452,113 @@ void NLA_OT_add_transition (wmOperatorType *ot) ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } +/* ******************** Add Meta-Strip Operator ***************************** */ +/* Add new meta-strips incorporating the selected strips */ + +/* add the specified action as new strip */ +static int nlaedit_add_meta_exec (bContext *C, wmOperator *op) +{ + bAnimContext ac; + + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* get a list of the editable tracks being shown in the NLA */ + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* for each track, find pairs of strips to add transitions to */ + for (ale= anim_data.first; ale; ale= ale->next) { + NlaTrack *nlt= (NlaTrack *)ale->data; + + /* create meta-strips from the continuous chains of selected strips */ + BKE_nlastrips_make_metas(&nlt->strips, 0); + } + + /* free temp data */ + BLI_freelistN(&anim_data); + + /* set notifier that things have changed */ + ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); + WM_event_add_notifier(C, NC_SCENE, NULL); + + /* done */ + return OPERATOR_FINISHED; +} + +void NLA_OT_add_meta (wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Add Meta-Strips"; + ot->idname= "NLA_OT_add_meta"; + ot->description= "Add new meta-strips incorporating the selected strips."; + + /* api callbacks */ + ot->exec= nlaedit_add_meta_exec; + ot->poll= nlaop_poll_tweakmode_off; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +/* ******************** Remove Meta-Strip Operator ***************************** */ +/* Separate out the strips held by the selected meta-strips */ + +static int nlaedit_remove_meta_exec (bContext *C, wmOperator *op) +{ + bAnimContext ac; + + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* get a list of the editable tracks being shown in the NLA */ + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* for each track, find pairs of strips to add transitions to */ + for (ale= anim_data.first; ale; ale= ale->next) { + NlaTrack *nlt= (NlaTrack *)ale->data; + + /* clear all selected meta-strips, regardless of whether they are temporary or not */ + BKE_nlastrips_clear_metas(&nlt->strips, 1, 0); + } + + /* free temp data */ + BLI_freelistN(&anim_data); + + /* set notifier that things have changed */ + ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); + WM_event_add_notifier(C, NC_SCENE, NULL); + + /* done */ + return OPERATOR_FINISHED; +} + +void NLA_OT_remove_meta (wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Remove Meta-Strips"; + ot->idname= "NLA_OT_remove_meta"; + ot->description= "Separate out the strips held by the selected meta-strips."; + + /* api callbacks */ + ot->exec= nlaedit_remove_meta_exec; + ot->poll= nlaop_poll_tweakmode_off; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + /* ******************** Duplicate Strips Operator ************************** */ /* Duplicates the selected NLA-Strips, putting them on new tracks above the one * the originals were housed in. @@ -1047,9 +1153,9 @@ static int nlaedit_snap_exec (bContext *C, wmOperator *op) bAnimListElem *ale; int filter; - Scene *scene= ac.scene; + Scene *scene; int mode = RNA_enum_get(op->ptr, "type"); - const float secf = (float)FPS; + float secf; /* get editor data */ if (ANIM_animdata_get_context(C, &ac) == 0) @@ -1059,17 +1165,28 @@ static int nlaedit_snap_exec (bContext *C, wmOperator *op) filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT); ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + /* get some necessary vars */ + scene= ac.scene; + secf= (float)FPS; + /* since we may add tracks, perform this in reverse order */ for (ale= anim_data.last; ale; ale= ale->prev) { ListBase tmp_strips = {NULL, NULL}; + AnimData *adt= BKE_animdata_from_id(ale->id); NlaTrack *nlt= (NlaTrack *)ale->data; NlaStrip *strip, *stripn; + NlaTrack *track; - /* first pass: move all selected strips to a separate buffer, and apply snapping to them */ + /* create meta-strips from the continuous chains of selected strips */ + BKE_nlastrips_make_metas(&nlt->strips, 1); + + /* apply the snapping to all the temp meta-strips, then put them in a separate list to be added + * back to the original only if they still fit + */ for (strip= nlt->strips.first; strip; strip= stripn) { stripn= strip->next; - if (strip->flag & NLASTRIP_FLAG_SELECT) { + if (strip->flag & NLASTRIP_FLAG_TEMP_META) { float start, end; /* get the existing end-points */ @@ -1098,13 +1215,32 @@ static int nlaedit_snap_exec (bContext *C, wmOperator *op) /* get new endpoint based on start-point (and old length) */ strip->end= strip->start + (end - start); + /* apply transforms to meta-strip to its children */ + BKE_nlameta_flush_transforms(strip); + /* remove strip from track, and add to the temp buffer */ BLI_remlink(&nlt->strips, strip); BLI_addtail(&tmp_strips, strip); } } - // TODO: finish this... + /* try adding each meta-strip back to the track one at a time, to make sure they'll fit */ + for (strip= tmp_strips.first; strip; strip= stripn) { + stripn= strip->next; + + /* remove from temp-strips list */ + BLI_remlink(&tmp_strips, strip); + + /* in case there's no space in the current track, try adding */ + if (BKE_nlatrack_add_strip(nlt, strip) == 0) { + /* need to add a new track above the current one */ + track= add_nlatrack(adt, nlt); + BKE_nlatrack_add_strip(track, strip); + } + } + + /* remove the meta-strips now that we're done */ + BKE_nlastrips_clear_metas(&nlt->strips, 0, 1); } /* free temp data */ diff --git a/source/blender/editors/space_nla/nla_header.c b/source/blender/editors/space_nla/nla_header.c index fc6db76ba65..9b9b21629cc 100644 --- a/source/blender/editors/space_nla/nla_header.c +++ b/source/blender/editors/space_nla/nla_header.c @@ -70,6 +70,8 @@ #include "ED_markers.h" +#include "nla_intern.h" + /* button events */ enum { B_REDR = 0, @@ -142,9 +144,18 @@ static void nla_edit_transformmenu(bContext *C, uiLayout *layout, void *arg_unus uiItemEnumO(layout, "Scale", 0, "TFM_OT_transform", "mode", TFM_TIME_SCALE); } +static void nla_edit_snapmenu(bContext *C, uiLayout *layout, void *arg_unused) +{ + uiItemEnumO(layout, NULL, 0, "NLA_OT_snap", "type", NLAEDIT_SNAP_CFRA); + uiItemEnumO(layout, NULL, 0, "NLA_OT_snap", "type", NLAEDIT_SNAP_NEAREST_FRAME); + uiItemEnumO(layout, NULL, 0, "NLA_OT_snap", "type", NLAEDIT_SNAP_NEAREST_SECOND); + uiItemEnumO(layout, NULL, 0, "NLA_OT_snap", "type", NLAEDIT_SNAP_NEAREST_MARKER); +} + static void nla_editmenu(bContext *C, uiLayout *layout, void *arg_unused) { uiItemMenuF(layout, "Transform", 0, nla_edit_transformmenu); + uiItemMenuF(layout, "Snap", 0, nla_edit_snapmenu); uiItemS(layout); @@ -173,6 +184,11 @@ static void nla_addmenu(bContext *C, uiLayout *layout, void *arg_unused) uiItemS(layout); + uiItemO(layout, NULL, 0, "NLA_OT_add_meta"); + uiItemO(layout, NULL, 0, "NLA_OT_remove_meta"); + + uiItemS(layout); + uiItemO(layout, NULL, 0, "NLA_OT_add_tracks"); uiItemBooleanO(layout, "Add Tracks Above Selected", 0, "NLA_OT_add_tracks", "above_selected", 1); } diff --git a/source/blender/editors/space_nla/nla_intern.h b/source/blender/editors/space_nla/nla_intern.h index 422686bb424..4391a019207 100644 --- a/source/blender/editors/space_nla/nla_intern.h +++ b/source/blender/editors/space_nla/nla_intern.h @@ -106,6 +106,9 @@ void NLA_OT_tweakmode_exit(wmOperatorType *ot); void NLA_OT_add_actionclip(wmOperatorType *ot); void NLA_OT_add_transition(wmOperatorType *ot); +void NLA_OT_add_meta(wmOperatorType *ot); +void NLA_OT_remove_meta(wmOperatorType *ot); + void NLA_OT_duplicate(wmOperatorType *ot); void NLA_OT_delete(wmOperatorType *ot); void NLA_OT_split(wmOperatorType *ot); @@ -116,6 +119,8 @@ void NLA_OT_move_down(wmOperatorType *ot); void NLA_OT_apply_scale(wmOperatorType *ot); void NLA_OT_clear_scale(wmOperatorType *ot); +void NLA_OT_snap(wmOperatorType *ot); + void NLA_OT_fmodifier_add(wmOperatorType *ot); diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c index 7caab02d6a0..25fd8db668c 100644 --- a/source/blender/editors/space_nla/nla_ops.c +++ b/source/blender/editors/space_nla/nla_ops.c @@ -146,6 +146,9 @@ void nla_operatortypes(void) WM_operatortype_append(NLA_OT_add_actionclip); WM_operatortype_append(NLA_OT_add_transition); + WM_operatortype_append(NLA_OT_add_meta); + WM_operatortype_append(NLA_OT_remove_meta); + WM_operatortype_append(NLA_OT_duplicate); WM_operatortype_append(NLA_OT_delete); WM_operatortype_append(NLA_OT_split); @@ -156,6 +159,8 @@ void nla_operatortypes(void) WM_operatortype_append(NLA_OT_apply_scale); WM_operatortype_append(NLA_OT_clear_scale); + WM_operatortype_append(NLA_OT_snap); + WM_operatortype_append(NLA_OT_fmodifier_add); } @@ -236,6 +241,10 @@ static void nla_keymap_main (wmWindowManager *wm, ListBase *keymap) /* add strips */ WM_keymap_add_item(keymap, "NLA_OT_add_actionclip", AKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "NLA_OT_add_transition", TKEY, KM_PRESS, KM_SHIFT, 0); + + /* meta-strips */ + WM_keymap_add_item(keymap, "NLA_OT_add_meta", GKEY, KM_PRESS, KM_SHIFT, 0); + WM_keymap_add_item(keymap, "NLA_OT_remove_meta", GKEY, KM_PRESS, KM_ALT, 0); /* duplicate */ WM_keymap_add_item(keymap, "NLA_OT_duplicate", DKEY, KM_PRESS, KM_SHIFT, 0); @@ -257,6 +266,9 @@ static void nla_keymap_main (wmWindowManager *wm, ListBase *keymap) /* clear scale */ WM_keymap_add_item(keymap, "NLA_OT_clear_scale", SKEY, KM_PRESS, KM_ALT, 0); + /* snap */ + WM_keymap_add_item(keymap, "NLA_OT_snap", SKEY, KM_PRESS, KM_SHIFT, 0); + /* add f-modifier */ WM_keymap_add_item(keymap, "NLA_OT_fmodifier_add", MKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0); diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h index a8220099a11..cb9dc8f0bc7 100644 --- a/source/blender/makesdna/DNA_anim_types.h +++ b/source/blender/makesdna/DNA_anim_types.h @@ -510,8 +510,8 @@ enum { /* temporary editing flags */ /* NLA-Strip is really just a temporary meta used to facilitate easier transform code */ - NLASTRIP_FLAG_TEMP_META = (1<<30), - NLASTRIP_FLAG_EDIT_TOUCHED = (1<<31), + NLASTRIP_FLAG_TEMP_META = (1<<14), + NLASTRIP_FLAG_EDIT_TOUCHED = (1<<15), } eNlaStrip_Flag; /* NLA Strip Type */ diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c index dfa496fd8f3..28a422dd601 100644 --- a/source/blender/makesrna/intern/rna_nla.c +++ b/source/blender/makesrna/intern/rna_nla.c @@ -207,6 +207,7 @@ void rna_def_nlastrip(BlenderRNA *brna) static EnumPropertyItem prop_type_items[] = { {NLASTRIP_TYPE_CLIP, "CLIP", 0, "Action Clip", "NLA Strip references some Action."}, {NLASTRIP_TYPE_TRANSITION, "TRANSITION", 0, "Transition", "NLA Strip 'transitions' between adjacent strips."}, + {NLASTRIP_TYPE_META, "META", 0, "Strip Container", "NLA Strip acts as a container for adjacent strips."}, {0, NULL, 0, NULL, NULL}}; static EnumPropertyItem prop_mode_blend_items[] = { {NLASTRIP_MODE_BLEND, "BLEND", 0, "Blend", "Results of strip and accumulated results are combined in ratio governed by influence."}, From f98c3ed70b86d12945078c288c2bd3288a297841 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Mon, 6 Jul 2009 12:24:09 +0000 Subject: [PATCH 089/114] NLA SoC: Fixes for Meta-Strips and Editing * Split strip (YKEY) now plays nicely with Transitions and Metas. Meta strips get split up into their child strips, while transitions are ignored. * Wrapped Meta_Strip->strips in RNA * Bugfixes in Meta-strip API functions to silence some runtime-errors... --- source/blender/blenkernel/BKE_nla.h | 1 + source/blender/blenkernel/intern/nla.c | 39 ++++++--- source/blender/editors/space_nla/nla_edit.c | 96 +++++++++++++-------- source/blender/makesrna/intern/rna_nla.c | 7 +- 4 files changed, 95 insertions(+), 48 deletions(-) diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index 3fcd799310e..5cb967c9c59 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -61,6 +61,7 @@ short BKE_nlastrips_add_strip(ListBase *strips, struct NlaStrip *strip); void BKE_nlastrips_make_metas(ListBase *strips, short temp); void BKE_nlastrips_clear_metas(ListBase *strips, short onlySel, short onlyTemp); +void BKE_nlastrips_clear_metastrip(ListBase *strips, struct NlaStrip *strip); short BKE_nlameta_add_strip(struct NlaStrip *mstrip, struct NlaStrip *strip); void BKE_nlameta_flush_transforms(struct NlaStrip *mstrip); diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 715f99c820f..a83fa0abe1e 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -650,6 +650,9 @@ void BKE_nlastrips_make_metas (ListBase *strips, short temp) /* set temp flag if appropriate (i.e. for transform-type editing) */ if (temp) mstrip->flag |= NLASTRIP_FLAG_TEMP_META; + + /* set default repeat/scale values to prevent warnings */ + mstrip->repeat= mstrip->scale= 1.0f; /* make its start frame be set to the start frame of the current strip */ mstrip->start= strip->start; @@ -671,6 +674,28 @@ void BKE_nlastrips_make_metas (ListBase *strips, short temp) } } +/* Split a meta-strip into a set of normal strips */ +void BKE_nlastrips_clear_metastrip (ListBase *strips, NlaStrip *strip) +{ + NlaStrip *cs, *csn; + + /* sanity check */ + if ELEM(NULL, strips, strip) + return; + + /* move each one of the meta-strip's children before the meta-strip + * in the list of strips after unlinking them from the meta-strip + */ + for (cs= strip->strips.first; cs; cs= csn) { + csn= cs->next; + BLI_remlink(&strip->strips, cs); + BLI_insertlinkbefore(strips, strip, cs); + } + + /* free the meta-strip now */ + BLI_freelinkN(strips, strip); +} + /* Remove meta-strips (i.e. flatten the list of strips) from the top-level of the list of strips * sel: only consider selected meta-strips, otherwise all meta-strips are removed * onlyTemp: only remove the 'temporary' meta-strips used for transforms @@ -692,19 +717,7 @@ void BKE_nlastrips_clear_metas (ListBase *strips, short onlySel, short onlyTemp) /* if check if selection and 'temporary-only' considerations are met */ if ((onlySel==0) || (strip->flag & NLASTRIP_FLAG_SELECT)) { if ((!onlyTemp) || (strip->flag & NLASTRIP_FLAG_TEMP_META)) { - NlaStrip *cs, *csn; - - /* move each one of the meta-strip's children before the meta-strip - * in the list of strips after unlinking them from the meta-strip - */ - for (cs= strip->strips.first; cs; cs= csn) { - csn= cs->next; - BLI_remlink(&strip->strips, cs); - BLI_insertlinkbefore(strips, strip, cs); - } - - /* free the meta-strip now */ - BLI_freelinkN(strips, strip); + BKE_nlastrips_clear_metastrip(strips, strip); } } } diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index f7d4db17e2c..676d0aac1b1 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -736,6 +736,55 @@ void NLA_OT_delete (wmOperatorType *ot) // - multiple splits // - variable-length splits? +/* split a given Action-Clip strip */ +static void nlaedit_split_strip_actclip (NlaTrack *nlt, NlaStrip *strip) +{ + NlaStrip *nstrip; + float midframe, midaframe, len; + + /* calculate the frames to do the splitting at */ + /* strip extents */ + len= strip->end - strip->start; + if (IS_EQ(len, 0.0f)) + return; + else + midframe= strip->start + (len / 2.0f); + + /* action range */ + len= strip->actend - strip->actstart; + if (IS_EQ(len, 0.0f)) + midaframe= strip->actend; + else + midaframe= strip->actstart + (len / 2.0f); + + /* make a copy (assume that this is possible) and append + * it immediately after the current strip + */ + nstrip= copy_nlastrip(strip); + BLI_insertlinkafter(&nlt->strips, strip, nstrip); + + /* set the endpoint of the first strip and the start of the new strip + * to the midframe values calculated above + */ + strip->end= midframe; + nstrip->start= midframe; + + strip->actend= midaframe; + nstrip->actstart= midaframe; + + /* clear the active flag from the copy */ + nstrip->flag &= ~NLASTRIP_FLAG_ACTIVE; +} + +/* split a given Meta strip */ +static void nlaedit_split_strip_meta (NlaTrack *nlt, NlaStrip *strip) +{ + /* simply ungroup it for now... */ + BKE_nlastrips_clear_metastrip(&nlt->strips, strip); +} + +/* ----- */ + static int nlaedit_split_exec (bContext *C, wmOperator *op) { bAnimContext ac; @@ -755,47 +804,26 @@ static int nlaedit_split_exec (bContext *C, wmOperator *op) /* for each NLA-Track, split all selected strips into two strips */ for (ale= anim_data.first; ale; ale= ale->next) { NlaTrack *nlt= (NlaTrack *)ale->data; - NlaStrip *strip, *nstrip, *next; + NlaStrip *strip, *next; for (strip= nlt->strips.first; strip; strip= next) { next= strip->next; /* if selected, split the strip at its midpoint */ if (strip->flag & NLASTRIP_FLAG_SELECT) { - float midframe, midaframe, len; - - /* calculate the frames to do the splitting at */ - /* strip extents */ - len= strip->end - strip->start; - if (IS_EQ(len, 0.0f)) - continue; - else - midframe= strip->start + (len / 2.0f); + /* splitting method depends on the type of strip */ + switch (strip->type) { + case NLASTRIP_TYPE_CLIP: /* action-clip */ + nlaedit_split_strip_actclip(nlt, strip); + break; + + case NLASTRIP_TYPE_META: /* meta-strips need special handling */ + nlaedit_split_strip_meta(nlt, strip); + break; - /* action range */ - len= strip->actend - strip->actstart; - if (IS_EQ(len, 0.0f)) - midaframe= strip->actend; - else - midaframe= strip->actstart + (len / 2.0f); - - /* make a copy (assume that this is possible) and append - * it immediately after the current strip - */ - nstrip= copy_nlastrip(strip); - BLI_insertlinkafter(&nlt->strips, strip, nstrip); - - /* set the endpoint of the first strip and the start of the new strip - * to the midframe values calculated above - */ - strip->end= midframe; - nstrip->start= midframe; - - strip->actend= midaframe; - nstrip->actstart= midaframe; - - /* clear the active flag from the copy */ - nstrip->flag &= ~NLASTRIP_FLAG_ACTIVE; + default: /* for things like Transitions, do not split! */ + break; + } } } } diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c index 28a422dd601..dae1a611757 100644 --- a/source/blender/makesrna/intern/rna_nla.c +++ b/source/blender/makesrna/intern/rna_nla.c @@ -207,7 +207,7 @@ void rna_def_nlastrip(BlenderRNA *brna) static EnumPropertyItem prop_type_items[] = { {NLASTRIP_TYPE_CLIP, "CLIP", 0, "Action Clip", "NLA Strip references some Action."}, {NLASTRIP_TYPE_TRANSITION, "TRANSITION", 0, "Transition", "NLA Strip 'transitions' between adjacent strips."}, - {NLASTRIP_TYPE_META, "META", 0, "Strip Container", "NLA Strip acts as a container for adjacent strips."}, + {NLASTRIP_TYPE_META, "META", 0, "Meta", "NLA Strip acts as a container for adjacent strips."}, {0, NULL, 0, NULL, NULL}}; static EnumPropertyItem prop_mode_blend_items[] = { {NLASTRIP_MODE_BLEND, "BLEND", 0, "Blend", "Results of strip and accumulated results are combined in ratio governed by influence."}, @@ -308,6 +308,11 @@ void rna_def_nlastrip(BlenderRNA *brna) RNA_def_property_struct_type(prop, "FModifier"); RNA_def_property_ui_text(prop, "Modifiers", "Modifiers affecting all the F-Curves in the referenced Action."); + /* Strip's Sub-Strips (for Meta-Strips) */ + prop= RNA_def_property(srna, "strips", PROP_COLLECTION, PROP_NONE); + RNA_def_property_struct_type(prop, "NlaStrip"); + RNA_def_property_ui_text(prop, "NLA Strips", "NLA Strips that this strip acts as a container for (if it is of type Meta)."); + /* Settings - Values necessary for evaluation */ prop= RNA_def_property(srna, "influence", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 0.0f, 1.0f); From 905b1380054f42fe30b19fb37861057af4760e32 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 7 Jul 2009 02:12:50 +0000 Subject: [PATCH 090/114] NLA SoC: Start of integration of Meta-strips in Transform * Chains of selected strips are now converted to meta-strips before transforms begin, and converted back afterwards. This simplifies the transform code needed in later stages... * Transform-flushing code for Meta-Strips should now work. There seems to be a little bit of numeric inaccuracy problems somewhere, as two strips which met at the same frame can get separated when scaling. * Meta-strips now draw with proper text identification * Snapping strips now properly clears meta-strips if a moved strip needs to be moved into a new track to be accomodated. * Fixed a filter used by a selection-operator. --- source/blender/blenkernel/intern/nla.c | 45 +++++++++++++++---- source/blender/editors/space_nla/nla_draw.c | 12 ++++- source/blender/editors/space_nla/nla_edit.c | 3 ++ source/blender/editors/space_nla/nla_select.c | 2 +- .../editors/transform/transform_conversions.c | 23 ++++++++++ .../editors/transform/transform_generics.c | 15 +++++++ 6 files changed, 89 insertions(+), 11 deletions(-) diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index a83fa0abe1e..851a0d7b549 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -781,6 +781,8 @@ void BKE_nlameta_flush_transforms (NlaStrip *mstrip) { NlaStrip *strip; float oStart, oEnd, offset; + float oLen, nLen; + short scaleChanged= 0; /* sanity checks * - strip must exist @@ -806,16 +808,43 @@ void BKE_nlameta_flush_transforms (NlaStrip *mstrip) if (IS_EQ(oStart, mstrip->start) && IS_EQ(oEnd, mstrip->end)) return; + /* check if scale changed */ + oLen = oEnd - oStart; + nLen = mstrip->end - mstrip->start; + if (IS_EQ(nLen, oLen) == 0) + scaleChanged= 1; + /* for each child-strip, calculate new start/end points based on this new info */ for (strip= mstrip->strips.first; strip; strip= strip->next) { - //PointerRNA strip_ptr; - - /* firstly, just apply the changes in offset to both ends of the strip */ - strip->start += offset; - strip->end += offset; - - /* now, we need to fix the endpoint to take into account scaling */ - // TODO.. + if (scaleChanged) { + PointerRNA ptr; + float p1, p2, nStart, nEnd; + + /* compute positions of endpoints relative to old extents of strip */ + p1= (strip->start - oStart) / oLen; + p2= (strip->end - oStart) / oLen; + + /* compute the new strip endpoints using the proportions */ + nStart= (p1 * nLen) + mstrip->start; + nEnd= (p2 * nLen) + mstrip->start; + + /* firstly, apply the new positions manually, then apply using RNA + * - first time is to make sure no truncation errors from one endpoint not being + * set yet occur + * - second time is to make sure scale is computed properly... + */ + strip->start= nStart; + strip->end= nEnd; + + RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &ptr); + RNA_float_set(&ptr, "start_frame", nStart); + RNA_float_set(&ptr, "end_frame", nEnd); + } + else { + /* just apply the changes in offset to both ends of the strip */ + strip->start += offset; + strip->end += offset; + } /* finally, make sure the strip's children (if it is a meta-itself), get updated */ BKE_nlameta_flush_transforms(strip); diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index e31aebf0155..7b9f2faf08a 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -366,13 +366,21 @@ static void nla_draw_strip_text (NlaTrack *nlt, NlaStrip *strip, int index, View /* for now, just init the string with fixed-formats */ switch (strip->type) { case NLASTRIP_TYPE_TRANSITION: /* Transition */ - sprintf(str, "%d | Transition | %.2f %s %.2f", index, strip->start, dir, strip->end); + sprintf(str, "%d | Transition | %.2f %s %.2f", + index, strip->start, dir, strip->end); + break; + + case NLASTRIP_TYPE_META: /* Meta */ + sprintf(str, "%d | %sMeta | %.2f %s %.2f", + index, ((strip->flag & NLASTRIP_FLAG_TEMP_META)?"Temp-":""), + strip->start, dir, strip->end); break; case NLASTRIP_TYPE_CLIP: /* Action-Clip (default) */ default: if (strip->act) - sprintf(str, "%d | Act: %s | %.2f %s %.2f", index, strip->act->id.name+2, strip->start, dir, strip->end); + sprintf(str, "%d | Act: %s | %.2f %s %.2f", + index, strip->act->id.name+2, strip->start, dir, strip->end); else sprintf(str, "%d | Act: ", index); // xxx... need a better format? break; diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index 676d0aac1b1..d663b76d5fe 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -1264,6 +1264,9 @@ static int nlaedit_snap_exec (bContext *C, wmOperator *op) /* need to add a new track above the current one */ track= add_nlatrack(adt, nlt); BKE_nlatrack_add_strip(track, strip); + + /* clear temp meta-strips on this new track, as we may not be able to get back to it */ + BKE_nlastrips_clear_metas(&track->strips, 0, 1); } } diff --git a/source/blender/editors/space_nla/nla_select.c b/source/blender/editors/space_nla/nla_select.c index c238818dd1e..ca186dcf702 100644 --- a/source/blender/editors/space_nla/nla_select.c +++ b/source/blender/editors/space_nla/nla_select.c @@ -513,7 +513,7 @@ static void nlaedit_mselect_leftright (bContext *C, bAnimContext *ac, short left /* filter data */ - filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVESONLY); + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS); ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); /* select strips on the side where most data occurs */ diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index b2afaac23de..758be545fd0 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -2617,6 +2617,9 @@ static void createTransNlaData(bContext *C, TransInfo *t) NlaTrack *nlt= (NlaTrack *)ale->data; NlaStrip *strip; + /* make some meta-strips for chains of selected strips */ + BKE_nlastrips_make_metas(&nlt->strips, 1); + /* only consider selected strips */ for (strip= nlt->strips.first; strip; strip= strip->next) { // TODO: we can make strips have handles later on... @@ -4754,6 +4757,26 @@ void special_aftertrans_update(TransInfo *t) if (ANIM_animdata_context_getdata(&ac) == 0) return; + if (ac.datatype) + { + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + short filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NLATRACKS); + + /* get channels to work on */ + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + for (ale= anim_data.first; ale; ale= ale->next) { + NlaTrack *nlt= (NlaTrack *)ale->data; + + /* remove the temp metas */ + BKE_nlastrips_clear_metas(&nlt->strips, 0, 1); + } + + /* free temp memory */ + BLI_freelistN(&anim_data); + } + // XXX check on the calls below... we need some of these sanity checks //synchronize_action_strips(); //ANIM_editkeyframes_refresh(&ac); diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 1474a30fbed..e228dc2b13a 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -82,6 +82,7 @@ #include "BKE_key.h" #include "BKE_mesh.h" #include "BKE_modifier.h" +#include "BKE_nla.h" #include "BKE_object.h" #include "BKE_utildefines.h" #include "BKE_context.h" @@ -388,6 +389,20 @@ void recalcData(TransInfo *t) } } } + + /* loop over the TransDataNla again, flushing the transforms (since we use Metas to make transforms easier) */ + td= t->data; + for (i = 0; i < t->total; i++, td++) + { + if (td->extra) + { + TransDataNla *tdn= td->extra; + NlaStrip *strip= tdn->strip; + + // TODO: this may flush some things twice, but that's fine as there's no impact from that + BKE_nlameta_flush_transforms(strip); + } + } } else if (t->obedit) { if ELEM(t->obedit->type, OB_CURVE, OB_SURF) { From 2edef129be18fa8cb7d9c33b8bd76dc60d9e1dcf Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 7 Jul 2009 05:41:59 +0000 Subject: [PATCH 091/114] NLA SoC: Transform Code for NLA-Strips recoded (still buggy) Recoded the Transform code for NLA-Strips so that they can now be moved between strips and will not get truncated when they get moved into other non-moving strips. Todos: * The current code for moving strips between tracks is buggy (only goes up, and has a tendency to move up without being told to) * Auto-snapping doesn't work yet... --- source/blender/editors/include/ED_anim_api.h | 16 ++ source/blender/editors/space_nla/nla_header.c | 2 +- source/blender/editors/space_nla/nla_intern.h | 15 -- source/blender/editors/transform/transform.c | 10 +- source/blender/editors/transform/transform.h | 14 +- .../editors/transform/transform_conversions.c | 103 ++++++++-- .../editors/transform/transform_generics.c | 180 +++++++++++++----- .../blender/editors/transform/transform_ops.c | 4 +- 8 files changed, 255 insertions(+), 89 deletions(-) diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index 87811fa34f9..2745be978d2 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -228,6 +228,22 @@ typedef enum eAnimFilter_Flags { /* channel toggle-buttons */ #define ACHANNEL_BUTTON_WIDTH 16 + +/* -------------- NLA Channel Defines -------------- */ + +/* NLA channel heights */ +#define NLACHANNEL_FIRST -16 +#define NLACHANNEL_HEIGHT 24 +#define NLACHANNEL_HEIGHT_HALF 12 +#define NLACHANNEL_SKIP 2 +#define NLACHANNEL_STEP (NLACHANNEL_HEIGHT + NLACHANNEL_SKIP) + +/* channel widths */ +#define NLACHANNEL_NAMEWIDTH 200 + +/* channel toggle-buttons */ +#define NLACHANNEL_BUTTON_WIDTH 16 + /* ---------------- API -------------------- */ /* Obtain list of filtered Animation channels to operate on. diff --git a/source/blender/editors/space_nla/nla_header.c b/source/blender/editors/space_nla/nla_header.c index 9b9b21629cc..9a2806ed9c1 100644 --- a/source/blender/editors/space_nla/nla_header.c +++ b/source/blender/editors/space_nla/nla_header.c @@ -139,7 +139,7 @@ static void nla_selectmenu(bContext *C, uiLayout *layout, void *arg_unused) static void nla_edit_transformmenu(bContext *C, uiLayout *layout, void *arg_unused) { // XXX these operators may change for NLA... - uiItemEnumO(layout, "Grab/Move", 0, "TFM_OT_transform", "mode", TFM_TIME_TRANSLATE); + uiItemEnumO(layout, "Grab/Move", 0, "TFM_OT_transform", "mode", TFM_TRANSLATION); uiItemEnumO(layout, "Extend", 0, "TFM_OT_transform", "mode", TFM_TIME_EXTEND); uiItemEnumO(layout, "Scale", 0, "TFM_OT_transform", "mode", TFM_TIME_SCALE); } diff --git a/source/blender/editors/space_nla/nla_intern.h b/source/blender/editors/space_nla/nla_intern.h index 4391a019207..3d8bfcd0546 100644 --- a/source/blender/editors/space_nla/nla_intern.h +++ b/source/blender/editors/space_nla/nla_intern.h @@ -33,21 +33,6 @@ /* **************************************** */ /* Macros, etc. only used by NLA */ -/* -------------- NLA Channel Defines -------------- */ - -/* NLA channel heights */ -#define NLACHANNEL_FIRST -16 -#define NLACHANNEL_HEIGHT 24 -#define NLACHANNEL_HEIGHT_HALF 12 -#define NLACHANNEL_SKIP 2 -#define NLACHANNEL_STEP (NLACHANNEL_HEIGHT + NLACHANNEL_SKIP) - -/* channel widths */ -#define NLACHANNEL_NAMEWIDTH 200 - -/* channel toggle-buttons */ -#define NLACHANNEL_BUTTON_WIDTH 16 - /* **************************************** */ /* space_nla.c / nla_buttons.c */ diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 9d8371afd61..9fbcfc71082 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -162,7 +162,7 @@ void convertViewVec(TransInfo *t, float *vec, short dx, short dy) vec[1]= aspy*(v2d->cur.ymax-v2d->cur.ymin)*(dy)/divy; vec[2]= 0.0f; } - else if(t->spacetype==SPACE_IPO) { + else if(ELEM(t->spacetype, SPACE_IPO, SPACE_NLA)) { View2D *v2d = t->view; float divx, divy; @@ -212,7 +212,7 @@ void projectIntView(TransInfo *t, float *vec, int *adr) UI_view2d_to_region_no_clip(t->view, v[0], v[1], adr, adr+1); } - else if(t->spacetype==SPACE_IPO) { + else if(ELEM(t->spacetype, SPACE_IPO, SPACE_NLA)) { int out[2] = {0, 0}; UI_view2d_view_to_region((View2D *)t->view, vec[0], vec[1], out, out+1); @@ -241,7 +241,7 @@ void projectFloatView(TransInfo *t, float *vec, float *adr) adr[0]= a[0]; adr[1]= a[1]; } - else if(t->spacetype==SPACE_IPO) { + else if(ELEM(t->spacetype, SPACE_IPO, SPACE_NLA)) { int a[2]; projectIntView(t, vec, a); @@ -1324,10 +1324,10 @@ int initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event, int case TFM_TIME_EXTEND: /* now that transdata has been made, do like for TFM_TIME_TRANSLATE (for most Animation * Editors because they have only 1D transforms for time values) or TFM_TRANSLATION - * (for Graph Editor only since it uses 'standard' transforms to get 2D movement) + * (for Graph/NLA Editors only since they uses 'standard' transforms to get 2D movement) * depending on which editor this was called from */ - if (t->spacetype == SPACE_IPO) + if ELEM(t->spacetype, SPACE_IPO, SPACE_NLA) initTranslation(t); else initTimeTranslate(t); diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 1b35701a753..65edae6fca8 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -163,9 +163,17 @@ typedef struct TransDataSeq { /* for NLA transform (stored in td->extra pointer) */ typedef struct TransDataNla { - struct NlaStrip *strip; /* NLA-strip that handle belongs to */ - float val; /* value for the handle that the transform tools write to */ - int handle; /* handle-index, 0 for start, 1 for end */ + struct NlaTrack *oldTrack; /* Original NLA-Track that the strip belongs to */ + struct NlaTrack *nlt; /* Current NLA-Track that the strip belongs to */ + + struct NlaStrip *strip; /* NLA-strip this data represents */ + + /* dummy values for transform to write in - must have 3 elements... */ + float h1[3]; /* start handle */ + float h2[3]; /* end handle */ + + int trackIndex; /* index of track that strip is currently in */ + int handle; /* handle-index: 0 for dummy entry, -1 for start, 1 for end, 2 for both ends */ } TransDataNla; typedef struct TransData { diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 758be545fd0..76720600327 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -2661,34 +2661,104 @@ static void createTransNlaData(bContext *C, TransInfo *t) /* transition strips can't get directly transformed */ if (strip->type != NLASTRIP_TYPE_TRANSITION) { if (strip->flag & NLASTRIP_FLAG_SELECT) { + /* our transform data is constructed as follows: + * - only the handles on the right side of the current-frame get included + * - td structs are transform-elements operated on by the transform system + * and represent a single handle. The storage/pointer used (val or loc) depends on + * whether we're scaling or transforming. Ultimately though, the handles + * the td writes to will simply be a dummy in tdn + * - for each strip being transformed, a single tdn struct is used, so in some + * cases, there will need to be 1 of these tdn elements in the array skipped... + */ + float center[3], yval; + + /* firstly, init tdn settings */ + tdn->oldTrack= tdn->nlt= nlt; + tdn->strip= strip; + tdn->trackIndex= BLI_findindex(&nlt->strips, strip); + + yval= (float)(tdn->trackIndex * NLACHANNEL_SKIP); + + tdn->h1[0]= strip->start; + tdn->h1[1]= yval; + tdn->h2[0]= strip->end; + tdn->h2[1]= yval; + + center[0]= (float)CFRA; + center[1]= yval; + center[2]= 0.0f; + + /* set td's based on which handles are applicable */ if (FrameOnMouseSide(side, strip->start, (float)CFRA)) { - /* init the 'extra' data for NLA strip handles first */ - tdn->strip= strip; - tdn->val= strip->start; - tdn->handle= 0; + /* just set tdn to assume that it only has one handle for now */ + tdn->handle= -1; /* now, link the transform data up to this data */ - td->val= &tdn->val; - td->ival= tdn->val; + if (t->mode == TFM_TRANSLATION) { + td->loc= tdn->h1; + VECCOPY(td->iloc, tdn->h1); + + /* store all the other gunk that is required by transform */ + VECCOPY(td->center, center); + memset(td->axismtx, 0, sizeof(td->axismtx)); + td->axismtx[2][2] = 1.0f; + + td->ext= NULL; td->tdi= NULL; td->val= NULL; + + td->flag |= TD_SELECTED; + td->dist= 0.0f; + + Mat3One(td->mtx); + Mat3One(td->smtx); + } + else { + td->val= &tdn->h1[0]; + td->ival= tdn->h1[0]; + } + td->extra= tdn; td++; - tdn++; } if (FrameOnMouseSide(side, strip->end, (float)CFRA)) { - /* init the 'extra' data for NLA strip handles first */ - tdn->strip= strip; - tdn->val= strip->end; - tdn->handle= 1; + /* if tdn is already holding the start handle, then we're doing both, otherwise, only end */ + tdn->handle= (tdn->handle) ? 2 : 1; /* now, link the transform data up to this data */ - td->val= &tdn->val; - td->ival= tdn->val; + if (t->mode == TFM_TRANSLATION) { + td->loc= tdn->h2; + VECCOPY(td->iloc, tdn->h2); + + /* store all the other gunk that is required by transform */ + VECCOPY(td->center, center); + memset(td->axismtx, 0, sizeof(td->axismtx)); + td->axismtx[2][2] = 1.0f; + + td->ext= NULL; td->tdi= NULL; td->val= NULL; + + td->flag |= TD_SELECTED; + td->dist= 0.0f; + + Mat3One(td->mtx); + Mat3One(td->smtx); + } + else { + td->val= &tdn->h2[0]; + td->ival= tdn->h2[0]; + } + td->extra= tdn; td++; - tdn++; } + + /* if both handles were used, skip the next tdn (i.e. leave it blank) since the counting code is dumb... + * otherwise, just advance to the next one... + */ + if (tdn->handle == 2) + tdn += 2; + else + tdn++; } } } @@ -4739,7 +4809,6 @@ void special_aftertrans_update(TransInfo *t) ANIM_editkeyframes_refresh(&ac); } else if (t->spacetype == SPACE_NLA) { - SpaceNla *snla= (SpaceNla *)t->sa->spacedata.first; Scene *scene; bAnimContext ac; @@ -4769,6 +4838,10 @@ void special_aftertrans_update(TransInfo *t) for (ale= anim_data.first; ale; ale= ale->next) { NlaTrack *nlt= (NlaTrack *)ale->data; + /* make sure strips are in order again */ + // FIXME: this is buggy + //BKE_nlatrack_sort_strips(nlt); + /* remove the temp metas */ BKE_nlastrips_clear_metas(&nlt->strips, 0, 1); } diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index e228dc2b13a..9928aea21d0 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -340,69 +340,153 @@ void recalcData(TransInfo *t) } } else if (t->spacetype == SPACE_NLA) { - TransData *td= t->data; + TransDataNla *tdn= (TransDataNla *)t->customData; int i; - /* for each point we've captured, look at its 'extra' data, which is basically a wrapper around the strip - * it is for + some extra storage for the values that get set, and use RNA to set this value (performing validation - * work so that we don't need to repeat it here) + /* for each strip we've got, perform some additional validation of the values that got set before + * using RNA to set the value (which does some special operations when setting these values to make + * sure that everything works ok) */ - for (i = 0; i < t->total; i++, td++) - { - if (td->extra) - { - TransDataNla *tdn= td->extra; - NlaStrip *strip= tdn->strip; + for (i = 0; i < t->total; i++, tdn++) { + NlaStrip *strip= tdn->strip; + PointerRNA strip_ptr; + short pExceeded, nExceeded, iter; + int delta_y1, delta_y2; + + /* if this tdn has no handles, that means it is just a dummy that should be skipped */ + if (tdn->handle == 0) + continue; - /* if we're just cancelling (i.e. the user aborted the transform), - * just restore the data by directly overwriting the values with the original - * ones (i.e. don't go through RNA), as we get some artifacts... + /* if cancelling transform, just write the values without validating, then move on */ + if (t->state == TRANS_CANCEL) { + /* clear the values by directly overwriting the originals, but also need to restore + * endpoints of neighboring transition-strips */ - if (t->state == TRANS_CANCEL) { - /* clear the values by directly overwriting the originals, but also need to restore - * endpoints of neighboring transition-strips + + /* start */ + strip->start= tdn->h1[0]; + + if ((strip->prev) && (strip->prev->type == NLASTRIP_TYPE_TRANSITION)) + strip->prev->end= tdn->h1[0]; + + /* end */ + strip->end= tdn->h2[0]; + + if ((strip->next) && (strip->next->type == NLASTRIP_TYPE_TRANSITION)) + strip->next->start= tdn->h2[0]; + + /* restore to original track (if needed) */ + if (tdn->oldTrack != tdn->nlt) { + /* just append to end of list for now, since strips get sorted in special_aftertrans_update() */ + BLI_remlink(&tdn->nlt->strips, strip); + BLI_addtail(&tdn->oldTrack->strips, strip); + } + + continue; + } + + /* firstly, check if the proposed transform locations would overlap with any neighbouring strips + * (barring transitions) which are absolute barriers since they are not being moved + * + * this is done as a iterative procedure (done 5 times max for now) + */ + for (iter=0; iter < 5; iter++) { + pExceeded= ((strip->prev) && (strip->prev->type != NLASTRIP_TYPE_TRANSITION) && (tdn->h1[0] < strip->prev->end)); + nExceeded= ((strip->next) && (strip->next->type != NLASTRIP_TYPE_TRANSITION) && (tdn->h2[0] > strip->next->start)); + + if ((pExceeded && nExceeded) || (iter == 4) ) { + /* both endpoints exceeded (or iteration ping-pong'd meaning that we need a compromise) + * - simply crop strip to fit within the bounds of the strips bounding it + * - if there were no neighbours, clear the transforms (make it default to the strip's current values) */ - if (tdn->handle) { - strip->end= tdn->val; - - if ((strip->next) && (strip->next->type == NLASTRIP_TYPE_TRANSITION)) - strip->next->start= tdn->val; + if (strip->prev && strip->next) { + tdn->h1[0]= strip->prev->end; + tdn->h2[0]= strip->next->start; } else { - strip->start= tdn->val; - - if ((strip->prev) && (strip->prev->type == NLASTRIP_TYPE_TRANSITION)) - strip->prev->end= tdn->val; + tdn->h1[0]= strip->start; + tdn->h2[0]= strip->end; + } + } + else if (nExceeded) { + /* move backwards */ + float offset= tdn->h2[0] - strip->next->start; + + tdn->h1[0] -= offset; + tdn->h2[0] -= offset; + } + else if (pExceeded) { + /* more forwards */ + float offset= strip->prev->end - tdn->h1[0]; + + tdn->h1[0] += offset; + tdn->h2[0] += offset; + } + else /* all is fine and well */ + break; + } + + /* use RNA to write the values... */ + // TODO: do we need to write in 2 passes to make sure that no truncation goes on? + RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr); + + RNA_float_set(&strip_ptr, "start_frame", tdn->h1[0]); + RNA_float_set(&strip_ptr, "end_frame", tdn->h2[0]); + + /* flush transforms to child strips (since this should be a meta) */ + BKE_nlameta_flush_transforms(strip); + + + /* now, check if we need to try and move track + * - we need to calculate both, as only one may have been altered by transform if only 1 handle moved + */ + // FIXME: the conversion from vertical distance to track index needs work! + delta_y1= ((int)tdn->h1[0] / NLACHANNEL_SKIP - tdn->trackIndex); + delta_y2= ((int)tdn->h2[0] / NLACHANNEL_SKIP - tdn->trackIndex); + + if (delta_y1 || delta_y2) { + NlaTrack *track; + int delta = (delta_y2) ? delta_y2 : delta_y1; + int n; + + /* move in the requested direction, checking at each layer if there's space for strip to pass through, + * stopping on the last track available or that we're able to fit in + */ + if (delta > 0) { + for (track=tdn->nlt->next, n=0; (track) && (n < delta); track=track->next, n++) { + /* check if space in this track for the strip */ + if (BKE_nlatrack_has_space(track, strip->start, strip->end)) { + /* move strip to this track */ + BLI_remlink(&tdn->nlt->strips, strip); + BKE_nlatrack_add_strip(track, strip); + + tdn->nlt= track; + tdn->trackIndex += (n + 1); /* + 1, since n==0 would mean that we didn't change track */ + } + else /* can't move any further */ + break; } } else { - PointerRNA strip_ptr; + /* make delta 'positive' before using it, since we now know to go backwards */ + delta= -delta; - /* make RNA-pointer */ - RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr); - - /* write the value set by the transform tools to the appropriate property using RNA */ - if (tdn->handle) - RNA_float_set(&strip_ptr, "end_frame", tdn->val); - else - RNA_float_set(&strip_ptr, "start_frame", tdn->val); + for (track=tdn->nlt->prev, n=0; (track) && (n < delta); track=track->prev, n++) { + /* check if space in this track for the strip */ + if (BKE_nlatrack_has_space(track, strip->start, strip->end)) { + /* move strip to this track */ + BLI_remlink(&tdn->nlt->strips, strip); + BKE_nlatrack_add_strip(track, strip); + + tdn->nlt= track; + tdn->trackIndex -= (n - 1); /* - 1, since n==0 would mean that we didn't change track */ + } + else /* can't move any further */ + break; + } } } } - - /* loop over the TransDataNla again, flushing the transforms (since we use Metas to make transforms easier) */ - td= t->data; - for (i = 0; i < t->total; i++, td++) - { - if (td->extra) - { - TransDataNla *tdn= td->extra; - NlaStrip *strip= tdn->strip; - - // TODO: this may flush some things twice, but that's fine as there's no impact from that - BKE_nlameta_flush_transforms(strip); - } - } } else if (t->obedit) { if ELEM(t->obedit->type, OB_CURVE, OB_SURF) { diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 28606932c64..ecb58831118 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -609,10 +609,10 @@ void transform_keymap_for_space(struct wmWindowManager *wm, struct ListBase *key break; case SPACE_NLA: km= WM_keymap_add_item(keymap, "TFM_OT_transform", GKEY, KM_PRESS, 0, 0); - RNA_int_set(km->ptr, "mode", TFM_TIME_TRANSLATE); + RNA_int_set(km->ptr, "mode", TFM_TRANSLATION); km= WM_keymap_add_item(keymap, "TFM_OT_transform", EVT_TWEAK_S, KM_ANY, 0, 0); - RNA_int_set(km->ptr, "mode", TFM_TIME_TRANSLATE); + RNA_int_set(km->ptr, "mode", TFM_TRANSLATION); km= WM_keymap_add_item(keymap, "TFM_OT_transform", EKEY, KM_PRESS, 0, 0); RNA_int_set(km->ptr, "mode", TFM_TIME_EXTEND); From 5fc61f03c12e291fa72fb3e60e5730300165aa3c Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 7 Jul 2009 06:16:06 +0000 Subject: [PATCH 092/114] NLA SoC: Fixes for bugs in transform code from previous commit * The code to move strips between tracks now works (though it can still be a bit too eager to change tracks half-way through some transforms). Strips are moved up/down one strip at a time, depending on whether there is any space in the next-track in the direction you direct it to move in. * Auto-snapping works again. Also enabled snap-to-marker option for Graph Editor here. --- .../editors/transform/transform_conversions.c | 4 +-- .../editors/transform/transform_generics.c | 25 +++++++++++++++---- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 76720600327..fafdfcc7602 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -2677,7 +2677,7 @@ static void createTransNlaData(bContext *C, TransInfo *t) tdn->strip= strip; tdn->trackIndex= BLI_findindex(&nlt->strips, strip); - yval= (float)(tdn->trackIndex * NLACHANNEL_SKIP); + yval= (float)(tdn->trackIndex * NLACHANNEL_STEP); tdn->h1[0]= strip->start; tdn->h1[1]= yval; @@ -3688,7 +3688,7 @@ void flushTransGraphData(TransInfo *t) break; case SACTSNAP_MARKER: /* snap to nearest marker */ - //td2d->loc[0]= (float)find_nearest_marker_time(td2d->loc[0]); + td2d->loc[0]= (float)ED_markers_find_nearest_marker_time(&t->scene->markers, td2d->loc[0]); break; } } diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 9928aea21d0..2ff3cd807cd 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -59,9 +59,7 @@ //#include "BIF_screen.h" //#include "BIF_mywindow.h" #include "BIF_gl.h" -//#include "BIF_editaction.h" //#include "BIF_editmesh.h" -//#include "BIF_editnla.h" //#include "BIF_editsima.h" //#include "BIF_editparticle.h" //#include "BIF_meshtools.h" @@ -91,6 +89,7 @@ #include "ED_armature.h" #include "ED_image.h" #include "ED_keyframing.h" +#include "ED_markers.h" #include "ED_mesh.h" #include "ED_space_api.h" #include "ED_uvedit.h" @@ -341,6 +340,7 @@ void recalcData(TransInfo *t) } else if (t->spacetype == SPACE_NLA) { TransDataNla *tdn= (TransDataNla *)t->customData; + SpaceNla *snla= (SpaceNla *)t->sa->spacedata.first; int i; /* for each strip we've got, perform some additional validation of the values that got set before @@ -375,6 +375,9 @@ void recalcData(TransInfo *t) if ((strip->next) && (strip->next->type == NLASTRIP_TYPE_TRANSITION)) strip->next->start= tdn->h2[0]; + /* flush transforms to child strips (since this should be a meta) */ + BKE_nlameta_flush_transforms(strip); + /* restore to original track (if needed) */ if (tdn->oldTrack != tdn->nlt) { /* just append to end of list for now, since strips get sorted in special_aftertrans_update() */ @@ -426,6 +429,19 @@ void recalcData(TransInfo *t) break; } + /* handle auto-snapping */ + switch (snla->autosnap) { + case SACTSNAP_FRAME: /* snap to nearest frame */ + tdn->h1[0]= (float)( floor(tdn->h1[0]+0.5f) ); + tdn->h2[0]= (float)( floor(tdn->h2[0]+0.5f) ); + break; + + case SACTSNAP_MARKER: /* snap to nearest marker */ + tdn->h1[0]= (float)ED_markers_find_nearest_marker_time(&t->scene->markers, tdn->h1[0]); + tdn->h2[0]= (float)ED_markers_find_nearest_marker_time(&t->scene->markers, tdn->h2[0]); + break; + } + /* use RNA to write the values... */ // TODO: do we need to write in 2 passes to make sure that no truncation goes on? RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr); @@ -440,9 +456,8 @@ void recalcData(TransInfo *t) /* now, check if we need to try and move track * - we need to calculate both, as only one may have been altered by transform if only 1 handle moved */ - // FIXME: the conversion from vertical distance to track index needs work! - delta_y1= ((int)tdn->h1[0] / NLACHANNEL_SKIP - tdn->trackIndex); - delta_y2= ((int)tdn->h2[0] / NLACHANNEL_SKIP - tdn->trackIndex); + delta_y1= ((int)tdn->h1[1] / NLACHANNEL_STEP - tdn->trackIndex); + delta_y2= ((int)tdn->h2[1] / NLACHANNEL_STEP - tdn->trackIndex); if (delta_y1 || delta_y2) { NlaTrack *track; From 6a320f327700e5ef6774d29b0b7a4d4b1a45fa27 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 7 Jul 2009 06:21:38 +0000 Subject: [PATCH 093/114] NLA SoC: Auto-Snapping Fixes (Transform) Snap to nearest-second works again for NLA and Graph Editors --- .../editors/transform/transform_conversions.c | 19 ++++++++----------- .../editors/transform/transform_generics.c | 14 +++++++++++--- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index fafdfcc7602..53c8e08ee74 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -101,16 +101,13 @@ #include "BKE_context.h" #include "BKE_report.h" -//#include "BIF_editaction.h" //#include "BIF_editview.h" //#include "BIF_editlattice.h" //#include "BIF_editconstraint.h" //#include "BIF_editmesh.h" -//#include "BIF_editnla.h" //#include "BIF_editsima.h" //#include "BIF_editparticle.h" #include "BIF_gl.h" -//#include "BIF_keyframing.h" //#include "BIF_poseobject.h" //#include "BIF_meshtools.h" //#include "BIF_mywindow.h" @@ -127,6 +124,7 @@ #include "ED_keyframing.h" #include "ED_keyframes_edit.h" #include "ED_object.h" +#include "ED_markers.h" #include "ED_mesh.h" #include "ED_types.h" #include "ED_uvedit.h" @@ -134,13 +132,7 @@ #include "UI_view2d.h" -//#include "BSE_drawipo.h" //#include "BSE_edit.h" -//#include "BSE_editipo.h" -//#include "BSE_editipo_types.h" -//#include "BSE_editaction_types.h" - -//#include "BDR_drawaction.h" // list of keyframes in action //#include "BDR_editobject.h" // reset_slowparents() //#include "BDR_gpencil.h" @@ -3671,6 +3663,8 @@ void flushTransGraphData(TransInfo *t) SpaceIpo *sipo = (SpaceIpo *)t->sa->spacedata.first; TransData *td; TransData2D *td2d; + Scene *scene= t->scene; + double secf= FPS; int a; /* flush to 2d vector from internally used 3d vector */ @@ -3683,8 +3677,11 @@ void flushTransGraphData(TransInfo *t) */ if ((td->flag & TD_NOTIMESNAP)==0) { switch (sipo->autosnap) { - case SACTSNAP_FRAME: /* snap to nearest frame */ - td2d->loc[0]= (float)( floor(td2d->loc[0]+0.5f) ); + case SACTSNAP_FRAME: /* snap to nearest frame (or second if drawing seconds) */ + if (sipo->flag & SIPO_DRAWTIME) + td2d->loc[0]= (float)( floor((td2d->loc[0]/secf) + 0.5f) * secf ); + else + td2d->loc[0]= (float)( floor(td2d->loc[0]+0.5f) ); break; case SACTSNAP_MARKER: /* snap to nearest marker */ diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 2ff3cd807cd..9d111f39b6d 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -341,6 +341,8 @@ void recalcData(TransInfo *t) else if (t->spacetype == SPACE_NLA) { TransDataNla *tdn= (TransDataNla *)t->customData; SpaceNla *snla= (SpaceNla *)t->sa->spacedata.first; + Scene *scene= t->scene; + double secf= FPS; int i; /* for each strip we've got, perform some additional validation of the values that got set before @@ -431,9 +433,15 @@ void recalcData(TransInfo *t) /* handle auto-snapping */ switch (snla->autosnap) { - case SACTSNAP_FRAME: /* snap to nearest frame */ - tdn->h1[0]= (float)( floor(tdn->h1[0]+0.5f) ); - tdn->h2[0]= (float)( floor(tdn->h2[0]+0.5f) ); + case SACTSNAP_FRAME: /* snap to nearest frame/time */ + if (snla->flag & SNLA_DRAWTIME) { + tdn->h1[0]= (float)( floor((tdn->h1[0]/secf) + 0.5f) * secf ); + tdn->h2[0]= (float)( floor((tdn->h2[0]/secf) + 0.5f) * secf ); + } + else { + tdn->h1[0]= (float)( floor(tdn->h1[0]+0.5f) ); + tdn->h2[0]= (float)( floor(tdn->h2[0]+0.5f) ); + } break; case SACTSNAP_MARKER: /* snap to nearest marker */ From dd42ad590ed4a620b0c70eb844d0cf341014b290 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 7 Jul 2009 06:39:01 +0000 Subject: [PATCH 094/114] NLA SoC: Small cleanup in Graph Editor struct code (obsolete + commented out stuff) --- source/blender/makesdna/DNA_space_types.h | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 329a3aac148..fef82ee2b91 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -86,7 +86,6 @@ typedef struct SpaceInfo { } SpaceInfo; /* 'Graph' Editor (formerly known as the IPO Editor) */ -// XXX for now, we keep all old data... typedef struct SpaceIpo { SpaceLink *next, *prev; ListBase regionbase; /* storage of regions for inactive spaces */ @@ -96,10 +95,6 @@ typedef struct SpaceIpo { short blockhandler[8]; View2D v2d; /* depricated, copied to region */ - // 'IPO keys' - vertical lines for editing multiple keyframes at once - use Dopesheet instead for this? - //ListBase ipokey; // XXX it's not clear how these will come back yet - //short showkey; // XXX this doesn't need to be restored until ipokeys come back - struct bDopeSheet *ads; /* settings for filtering animation data (NOTE: we use a pointer due to code-linking issues) */ ListBase ghostCurves; /* sampled snapshots of F-Curves used as in-session guides */ @@ -107,7 +102,7 @@ typedef struct SpaceIpo { short mode; /* mode for the Graph editor (eGraphEdit_Mode) */ short flag; /* settings for Graph editor */ short autosnap; /* time-transform autosnapping settings for Graph editor (eAnimEdit_AutoSnap in DNA_action_types.h) */ - char pin, lock; + char pin, lock; // XXX old, unused vars that are probably going to be depreceated soon... } SpaceIpo; typedef struct SpaceButs { From 761241fcbbeb254cd78aca5f8bb62330ce9369ac Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 7 Jul 2009 06:56:29 +0000 Subject: [PATCH 095/114] NLA SoC: Current Frame can now be negative This commit is quite experimental, and might have to be reverted, but in quite a few places, the cleanups from this commit were already necessary. * I've left most of the image-handling functions alone, since I'm not sure how well they cope with negative indices. * Start/End frames cannot be negative for now... any specific reasons why they should be negative? --- source/blender/editors/animation/anim_ops.c | 8 +++++--- source/blender/editors/space_action/action_select.c | 2 +- source/blender/editors/space_buttons/buttons_header.c | 2 +- source/blender/editors/space_graph/graph_select.c | 2 +- source/blender/editors/space_nla/nla_select.c | 2 +- source/blender/editors/space_time/time_header.c | 5 ++++- source/blender/makesdna/DNA_scene_types.h | 4 ++++ source/blender/makesrna/intern/rna_constraint.c | 4 ++-- source/blender/makesrna/intern/rna_modifier.c | 8 ++++---- source/blender/makesrna/intern/rna_nla.c | 4 ++-- source/blender/makesrna/intern/rna_object.c | 2 +- source/blender/makesrna/intern/rna_particle.c | 10 +++++----- source/blender/makesrna/intern/rna_scene.c | 2 +- 13 files changed, 32 insertions(+), 23 deletions(-) diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c index e899cc1d520..10691c558bf 100644 --- a/source/blender/editors/animation/anim_ops.c +++ b/source/blender/editors/animation/anim_ops.c @@ -83,10 +83,12 @@ static void change_frame_apply(bContext *C, wmOperator *op) Scene *scene= CTX_data_scene(C); int cfra; - /* get frame, and clamp to MINFRAME */ + /* get frame, and clamp to MINAFRAME + * - not MINFRAME, since it's useful to be able to key a few-frames back + */ cfra= RNA_int_get(op->ptr, "frame"); - if (cfra < MINFRAME) cfra= MINFRAME; + if (cfra < MINAFRAME) cfra= MINAFRAME; CFRA= cfra; WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene); @@ -209,7 +211,7 @@ void ANIM_OT_change_frame(wmOperatorType *ot) ot->modal= change_frame_modal; /* rna */ - RNA_def_int(ot->srna, "frame", 0, 1, MAXFRAME, "Frame", "", 1, MAXFRAME); + RNA_def_int(ot->srna, "frame", 0, MINAFRAME, MAXFRAME, "Frame", "", MINAFRAME, MAXFRAME); } /* ****************** set preview range operator ****************************/ diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c index d45e32dd3bb..5b87c04b311 100644 --- a/source/blender/editors/space_action/action_select.c +++ b/source/blender/editors/space_action/action_select.c @@ -642,7 +642,7 @@ static void actkeys_mselect_leftright (bAnimContext *ac, short leftright, short memset(&bed, 0, sizeof(BeztEditFunc)); if (leftright == ACTKEYS_LRSEL_LEFT) { - bed.f1 = -MAXFRAMEF; + bed.f1 = MINAFRAMEF; bed.f2 = (float)(CFRA + FRAME_CLICK_THRESH); } else { diff --git a/source/blender/editors/space_buttons/buttons_header.c b/source/blender/editors/space_buttons/buttons_header.c index 7c622f172a2..99cc85d9a52 100644 --- a/source/blender/editors/space_buttons/buttons_header.c +++ b/source/blender/editors/space_buttons/buttons_header.c @@ -193,7 +193,7 @@ void buttons_header_buttons(const bContext *C, ARegion *ar) uiBlockEndAlign(block); xco+=XIC; - uiDefButI(block, NUM, B_NEWFRAME, "", (xco+20),yco,60,YIC, &(CTX_data_scene(C)->r.cfra), 1.0, MAXFRAMEF, 0, 0, "Displays Current Frame of animation. Click to change."); + uiDefButI(block, NUM, B_NEWFRAME, "", (xco+20),yco,60,YIC, &(CTX_data_scene(C)->r.cfra), MINAFRAMEF, MAXFRAMEF, 0, 0, "Displays Current Frame of animation. Click to change."); xco+= 80; /* always as last */ diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c index 11af86ca83b..c855222df02 100644 --- a/source/blender/editors/space_graph/graph_select.c +++ b/source/blender/editors/space_graph/graph_select.c @@ -763,7 +763,7 @@ static void graphkeys_mselect_leftright (bAnimContext *ac, short leftright, shor memset(&bed, 0, sizeof(BeztEditFunc)); if (leftright == GRAPHKEYS_LRSEL_LEFT) { - bed.f1 = -MAXFRAMEF; + bed.f1 = MINAFRAMEF; bed.f2 = (float)(CFRA + 0.1f); } else { diff --git a/source/blender/editors/space_nla/nla_select.c b/source/blender/editors/space_nla/nla_select.c index ca186dcf702..895d0dbf88a 100644 --- a/source/blender/editors/space_nla/nla_select.c +++ b/source/blender/editors/space_nla/nla_select.c @@ -501,7 +501,7 @@ static void nlaedit_mselect_leftright (bContext *C, bAnimContext *ac, short left /* get range, and get the right flag-setting mode */ if (leftright == NLAEDIT_LRSEL_LEFT) { - xmin = -MAXFRAMEF; + xmin = MINAFRAMEF; xmax = (float)(CFRA + FRAME_CLICK_THRESH); } else { diff --git a/source/blender/editors/space_time/time_header.c b/source/blender/editors/space_time/time_header.c index 29f31671670..da99849e594 100644 --- a/source/blender/editors/space_time/time_header.c +++ b/source/blender/editors/space_time/time_header.c @@ -536,9 +536,12 @@ void time_header_buttons(const bContext *C, ARegion *ar) xco += (short)(4.5 * XIC + 16); + /* MINAFRAMEF not MINFRAMEF, since MINAFRAMEF allows to set current frame negative + * to facilitate easier keyframing in some situations + */ uiDefButI(block, NUM, B_NEWFRAME, "", xco,yco, (int)3.5*XIC,YIC, - &(scene->r.cfra), MINFRAMEF, MAXFRAMEF, 0, 0, + &(scene->r.cfra), MINAFRAMEF, MAXFRAMEF, 0, 0, "Displays Current Frame of animation"); xco += (short)(3.5 * XIC + 16); diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 3549cdbe75f..6355e02a5e0 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -772,6 +772,10 @@ typedef struct Scene { #define MINFRAME 1 #define MINFRAMEF 1.0f +/* (minimum frame number for current-frame) */ +#define MINAFRAME -300000 +#define MINAFRAMEF -300000.0f + /* depricate this! */ #define TESTBASE(v3d, base) ( ((base)->flag & SELECT) && ((base)->lay & v3d->lay) && (((base)->object->restrictflag & OB_RESTRICT_VIEW)==0) ) #define TESTBASELIB(v3d, base) ( ((base)->flag & SELECT) && ((base)->lay & v3d->lay) && ((base)->object->id.lib==0) && (((base)->object->restrictflag & OB_RESTRICT_VIEW)==0)) diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index 5c4b6a95524..2a5df8f1488 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -729,13 +729,13 @@ static void rna_def_constraint_action(BlenderRNA *brna) prop= RNA_def_property(srna, "start_frame", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "start"); - RNA_def_property_range(prop, MINFRAME, MAXFRAME); + RNA_def_property_range(prop, MINAFRAME, MAXFRAME); RNA_def_property_ui_text(prop, "Start Frame", "First frame of the Action to use."); RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); prop= RNA_def_property(srna, "end_frame", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "end"); - RNA_def_property_range(prop, MINFRAME, MAXFRAME); + RNA_def_property_range(prop, MINAFRAME, MAXFRAME); RNA_def_property_ui_text(prop, "End Frame", "Last frame of the Action to use."); RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index 48bfdf70171..69d5c203abf 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -506,7 +506,7 @@ static void rna_def_modifier_build(BlenderRNA *brna) RNA_def_struct_ui_icon(srna, ICON_MOD_BUILD); prop= RNA_def_property(srna, "start", PROP_FLOAT, PROP_NONE); - RNA_def_property_range(prop, 1, MAXFRAMEF); + RNA_def_property_range(prop, MINAFRAMEF, MAXFRAMEF); RNA_def_property_ui_text(prop, "Start", "Specify the start frame of the effect."); RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Modifier_update"); @@ -660,18 +660,18 @@ static void rna_def_modifier_wave(BlenderRNA *brna) prop= RNA_def_property(srna, "time_offset", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "timeoffs"); - RNA_def_property_range(prop, -MAXFRAMEF, MAXFRAMEF); + RNA_def_property_range(prop, MINAFRAMEF, MAXFRAMEF); RNA_def_property_ui_text(prop, "Time Offset", "Either the starting frame (for positive speed) or ending frame (for negative speed.)"); RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Modifier_update"); prop= RNA_def_property(srna, "lifetime", PROP_FLOAT, PROP_NONE); - RNA_def_property_range(prop, -MAXFRAMEF, MAXFRAMEF); + RNA_def_property_range(prop, MINAFRAMEF, MAXFRAMEF); RNA_def_property_ui_text(prop, "Lifetime", ""); RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Modifier_update"); prop= RNA_def_property(srna, "damping_time", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "damp"); - RNA_def_property_range(prop, -MAXFRAMEF, MAXFRAMEF); + RNA_def_property_range(prop, MINAFRAMEF, MAXFRAMEF); RNA_def_property_ui_text(prop, "Damping Time", ""); RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Modifier_update"); diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c index dae1a611757..b0149d29e69 100644 --- a/source/blender/makesrna/intern/rna_nla.c +++ b/source/blender/makesrna/intern/rna_nla.c @@ -66,7 +66,7 @@ static void rna_NlaStrip_start_frame_set(PointerRNA *ptr, float value) } } else { - CLAMP(value, -MAXFRAME, data->end); + CLAMP(value, MINAFRAME, data->end); } data->start= value; } @@ -185,7 +185,7 @@ static void rna_NlaStrip_blend_out_set(PointerRNA *ptr, float value) static void rna_NlaStrip_action_start_frame_set(PointerRNA *ptr, float value) { NlaStrip *data= (NlaStrip*)ptr->data; - CLAMP(value, -MAXFRAME, data->actend); + CLAMP(value, MINAFRAME, data->actend); data->actstart= value; } diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index ca2c9d072fb..b33c5e480b5 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -1154,7 +1154,7 @@ static void rna_def_object(BlenderRNA *brna) prop= RNA_def_property(srna, "time_offset", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "sf"); - RNA_def_property_range(prop, -MAXFRAMEF, MAXFRAMEF); + RNA_def_property_range(prop, MINAFRAMEF, MAXFRAMEF); RNA_def_property_ui_text(prop, "Time Offset", "Animation offset in frames for IPO's and dupligroup instances."); RNA_def_property_update(prop, NC_OBJECT|ND_TRANSFORM, "rna_Object_update"); diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index d60a215b498..ba331efada1 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -161,8 +161,8 @@ static void rna_PartSettings_start_set(struct PointerRNA *ptr, float value) if(settings->type==PART_REACTOR && value < 1.0) value = 1.0; - else if (value < -30000.0f) //TODO: replace 30000 with MAXFRAMEF when available in 2.5 - value = -30000.0f; + else if (value < MINAFRAMEF) + value = MINAFRAMEF; settings->sta = value; } @@ -1066,19 +1066,19 @@ static void rna_def_particle_settings(BlenderRNA *brna) /* general values */ prop= RNA_def_property(srna, "start", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "sta");//optional if prop names are the same - RNA_def_property_range(prop, -30000.0f, 30000.0f); //TODO: replace 30000 with MAXFRAMEF when available in 2.5 + RNA_def_property_range(prop, MINAFRAMEF, MAXFRAMEF); RNA_def_property_float_funcs(prop, NULL, "rna_PartSettings_start_set", NULL); RNA_def_property_ui_text(prop, "Start", "Frame # to start emitting particles."); RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset"); prop= RNA_def_property(srna, "end", PROP_FLOAT, PROP_NONE); - RNA_def_property_range(prop, -30000.0f, 30000.0f); //TODO: replace 30000 with MAXFRAMEF when available in 2.5 + RNA_def_property_range(prop, MINAFRAMEF, MAXFRAMEF); RNA_def_property_float_funcs(prop, NULL, "rna_PartSettings_end_set", NULL); RNA_def_property_ui_text(prop, "End", "Frame # to stop emitting particles."); RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset"); prop= RNA_def_property(srna, "lifetime", PROP_FLOAT, PROP_NONE); - RNA_def_property_range(prop, 1.0f, 30000.0f); + RNA_def_property_range(prop, 1.0f, MAXFRAMEF); RNA_def_property_ui_text(prop, "Lifetime", "Specify the life span of the particles"); RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset"); diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 5f03b7167f4..2ad4a20f9a0 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -960,7 +960,7 @@ void RNA_def_scene(BlenderRNA *brna) prop= RNA_def_property(srna, "current_frame", PROP_INT, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_ANIMATEABLE); RNA_def_property_int_sdna(prop, NULL, "r.cfra"); - RNA_def_property_range(prop, MINFRAME, MAXFRAME); + RNA_def_property_range(prop, MINAFRAME, MAXFRAME); RNA_def_property_ui_text(prop, "Current Frame", ""); RNA_def_property_update(prop, NC_SCENE|ND_FRAME, "rna_Scene_frame_update"); From a86d20e5a26700beac595bd8aaccb646be0f802c Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 7 Jul 2009 07:29:21 +0000 Subject: [PATCH 096/114] NLA SoC: Quick hack - Reversed playback Animations can now be played back in reverse, by clicking on the reversed-playback button in the TimeLine header beside the play button (NEW ICON NEEDED HERE). I'm not sure how well this works with sound, but from what I gather, this can be quite useful for animators to use. --- .../blender/editors/include/ED_screen_types.h | 1 + source/blender/editors/screen/screen_edit.c | 5 ++- source/blender/editors/screen/screen_ops.c | 44 ++++++++++++++----- .../blender/editors/space_time/time_header.c | 32 ++++++++++++-- 4 files changed, 67 insertions(+), 15 deletions(-) diff --git a/source/blender/editors/include/ED_screen_types.h b/source/blender/editors/include/ED_screen_types.h index 37f2f4f051d..3ea5dfba65c 100644 --- a/source/blender/editors/include/ED_screen_types.h +++ b/source/blender/editors/include/ED_screen_types.h @@ -33,6 +33,7 @@ typedef struct ScreenAnimData { ARegion *ar; /* do not read from this, only for comparing if region exists */ int redraws; + int reverse; } ScreenAnimData; diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index 4e08310240c..6da00f12a25 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -1460,7 +1460,9 @@ void ED_screen_full_prevspace(bContext *C) ed_screen_fullarea(C, sa); } -/* redraws: uses defines from stime->redraws */ +/* redraws: uses defines from stime->redraws + * enable: 1 - forward on, -1 - backwards on, 0 - off + */ void ED_screen_animation_timer(bContext *C, int redraws, int enable) { bScreen *screen= CTX_wm_screen(C); @@ -1477,6 +1479,7 @@ void ED_screen_animation_timer(bContext *C, int redraws, int enable) screen->animtimer= WM_event_add_window_timer(win, TIMER0, (1.0/FPS)); sad->ar= CTX_wm_region(C); sad->redraws= redraws; + sad->reverse= (enable < 0); screen->animtimer->customdata= sad; } diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 5bf090e459b..80526dbdb6e 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -2067,19 +2067,40 @@ static int screen_animation_step(bContext *C, wmOperator *op, wmEvent *event) if(scene->audio.flag & AUDIO_SYNC) { int step = floor(wt->duration * FPS); - scene->r.cfra += step; + if (sad->reverse) // XXX does this option work with audio? + scene->r.cfra -= step; + else + scene->r.cfra += step; wt->duration -= ((float)step)/FPS; } - else - scene->r.cfra++; + else { + if (sad->reverse) + scene->r.cfra--; + else + scene->r.cfra++; + } - if (scene->r.psfra) { - if(scene->r.cfra > scene->r.pefra) - scene->r.cfra= scene->r.psfra; + if (sad->reverse) { + /* jump back to end */ + if (scene->r.psfra) { + if(scene->r.cfra < scene->r.psfra) + scene->r.cfra= scene->r.pefra; + } + else { + if(scene->r.cfra < scene->r.sfra) + scene->r.cfra= scene->r.efra; + } } else { - if(scene->r.cfra > scene->r.efra) - scene->r.cfra= scene->r.sfra; + /* jump back to start */ + if (scene->r.psfra) { + if(scene->r.cfra > scene->r.pefra) + scene->r.cfra= scene->r.psfra; + } + else { + if(scene->r.cfra > scene->r.efra) + scene->r.cfra= scene->r.sfra; + } } /* since we follow drawflags, we can't send notifier but tag regions ourselves */ @@ -2127,8 +2148,9 @@ static int screen_animation_play(bContext *C, wmOperator *op, wmEvent *event) ED_screen_animation_timer(C, 0, 0); } else { - /* todo: RNA properties to define play types */ - ED_screen_animation_timer(C, TIME_REGION|TIME_ALL_3D_WIN, 1); + int mode= (RNA_boolean_get(op->ptr, "reverse")) ? -1 : 1; + + ED_screen_animation_timer(C, TIME_REGION|TIME_ALL_3D_WIN, mode); if(screen->animtimer) { wmTimer *wt= screen->animtimer; @@ -2152,7 +2174,7 @@ void SCREEN_OT_animation_play(wmOperatorType *ot) ot->poll= ED_operator_screenactive; - + RNA_def_boolean(ot->srna, "reverse", 0, "Play in Reverse", "Animation is played backwards"); } /* ************** border select operator (template) ***************************** */ diff --git a/source/blender/editors/space_time/time_header.c b/source/blender/editors/space_time/time_header.c index da99849e594..9ffce53e572 100644 --- a/source/blender/editors/space_time/time_header.c +++ b/source/blender/editors/space_time/time_header.c @@ -373,6 +373,7 @@ static uiBlock *time_framemenu(bContext *C, ARegion *ar, void *arg_unused) #define B_REDRAWALL 750 #define B_TL_REW 751 #define B_TL_PLAY 752 +#define B_TL_RPLAY 760 #define B_TL_FF 753 #define B_TL_PREVKEY 754 #define B_TL_NEXTKEY 755 @@ -415,6 +416,18 @@ void do_time_buttons(bContext *C, void *arg, int event) sad->ar= time_top_left_3dwindow(screen); } + break; + case B_TL_RPLAY: + ED_screen_animation_timer(C, stime->redraws, -1); + + /* update region if TIME_REGION was set, to leftmost 3d window */ + if(screen->animtimer && (stime->redraws & TIME_REGION)) { + wmTimer *wt= screen->animtimer; + ScreenAnimData *sad= wt->customdata; + + sad->ar= time_top_left_3dwindow(screen); + } + break; case B_TL_STOP: ED_screen_animation_timer(C, 0, 0); @@ -553,14 +566,27 @@ void time_header_buttons(const bContext *C, ARegion *ar) xco, yco, XIC, YIC, 0, 0, 0, 0, 0, "Skip to previous keyframe (Ctrl PageDown)"); xco+= XIC+4; - if(CTX_wm_screen(C)->animtimer) + if(CTX_wm_screen(C)->animtimer) { + /* pause button is drawn centered between the two other buttons for now (saves drawing 2 buttons, or having position changes) */ + xco+= XIC/2 + 2; + uiDefIconBut(block, BUT, B_TL_STOP, ICON_PAUSE, xco, yco, XIC, YIC, 0, 0, 0, 0, 0, "Stop Playing Timeline"); - else + + xco+= XIC/2 + 2; + } + else { + // FIXME: the icon for this is crap + uiDefIconBut(block, BUT, B_TL_RPLAY, ICON_REW/*ICON_PLAY*/, + xco, yco, XIC, YIC, 0, 0, 0, 0, 0, "Play Timeline in Reverse"); + + xco+= XIC+4; + uiDefIconBut(block, BUT, B_TL_PLAY, ICON_PLAY, xco, yco, XIC, YIC, 0, 0, 0, 0, 0, "Play Timeline "); - + } xco+= XIC+4; + uiDefIconBut(block, BUT, B_TL_NEXTKEY, ICON_NEXT_KEYFRAME, xco, yco, XIC, YIC, 0, 0, 0, 0, 0, "Skip to next keyframe (Ctrl PageUp)"); xco+= XIC+4; From e22fefc2c8ef2c844d32d9aed23a04013cc364fb Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 7 Jul 2009 10:25:55 +0000 Subject: [PATCH 097/114] NLA SoC: Fixed bug with NLA-Transform Strip-sorting code was buggy, as it was trying to access an invalid pointer, so the call to sort strips after transform was temporarily disabled in previous commits. --- source/blender/blenkernel/intern/nla.c | 12 +++++++----- .../editors/transform/transform_conversions.c | 3 +-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 851a0d7b549..4dce9aebe24 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -546,26 +546,28 @@ short BKE_nlastrips_has_space (ListBase *strips, float start, float end) void BKE_nlastrips_sort_strips (ListBase *strips) { ListBase tmp = {NULL, NULL}; - NlaStrip *strip, *sstrip; + NlaStrip *strip, *sstrip, *stripn; /* sanity checks */ if ELEM(NULL, strips, strips->first) return; - + /* we simply perform insertion sort on this list, since it is assumed that per track, * there are only likely to be at most 5-10 strips */ - for (strip= strips->first; strip; strip= strip->next) { + for (strip= strips->first; strip; strip= stripn) { short not_added = 1; + stripn= strip->next; + /* remove this strip from the list, and add it to the new list, searching from the end of * the list, assuming that the lists are in order */ BLI_remlink(strips, strip); - for (sstrip= tmp.last; not_added && sstrip; sstrip= sstrip->prev) { + for (sstrip= tmp.last; sstrip; sstrip= sstrip->prev) { /* check if add after */ - if (sstrip->end < strip->start) { + if (sstrip->end <= strip->start) { BLI_insertlinkafter(&tmp, sstrip, strip); not_added= 0; break; diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 53c8e08ee74..0d19eeb913e 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -4836,8 +4836,7 @@ void special_aftertrans_update(TransInfo *t) NlaTrack *nlt= (NlaTrack *)ale->data; /* make sure strips are in order again */ - // FIXME: this is buggy - //BKE_nlatrack_sort_strips(nlt); + BKE_nlatrack_sort_strips(nlt); /* remove the temp metas */ BKE_nlastrips_clear_metas(&nlt->strips, 0, 1); From d1677e36b663f077312050ac46cea0de1b1212c2 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 7 Jul 2009 11:37:33 +0000 Subject: [PATCH 098/114] NLA SoC: Recoded way that Meta-Strips are Evaluated Previously, the quick-hack I coded for Meta-strips evaluation didn't really take into account the possibilities to use Meta-Strips as strips in their own right - i.e. reversed, muted, time-mapping-curves, influence-blending - were all unavailable. This commit makes the aforementioned capabilities of other strips available for Meta-Strips too. The evaluation is now kind-of recursive (as with most of the other methods which take them into account) so that each 'level' of strips get evaluated correctly within their frame-of-reference. TODO: * F-Modifier support for Metas... --- source/blender/blenkernel/intern/anim_sys.c | 166 +++++++++++--------- source/blender/blenkernel/intern/nla.c | 2 +- source/blender/blenkernel/nla_private.h | 6 + 3 files changed, 101 insertions(+), 73 deletions(-) diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 1d10744ac80..0aadb1825ad 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -627,11 +627,12 @@ static void nlastrip_evaluate_controls (NlaStrip *strip, float ctime) } } - -/* gets the strip active at the current time for a given list of strips */ -static NlaStrip *ctime_get_strip (ListBase *strips, short *side, float ctime) +/* gets the strip active at the current time for a list of strips for evaluation purposes */ +NlaEvalStrip *nlastrips_ctime_get_strip (ListBase *list, ListBase *strips, short index, float ctime) { NlaStrip *strip, *estrip=NULL; + NlaEvalStrip *nes; + short side= 0; /* loop over strips, checking if they fall within the range */ for (strip= strips->first; strip; strip= strip->next) { @@ -651,7 +652,7 @@ static NlaStrip *ctime_get_strip (ListBase *strips, short *side, float ctime) estrip= strip; /* side is 'before' regardless of whether there's a useful strip */ - *side= NES_TIME_BEFORE; + side= NES_TIME_BEFORE; } else { /* before next strip - previous strip has ended, but next hasn't begun, @@ -663,7 +664,7 @@ static NlaStrip *ctime_get_strip (ListBase *strips, short *side, float ctime) if (strip->extendmode != NLASTRIP_EXTEND_NOTHING) estrip= strip; - *side= NES_TIME_AFTER; + side= NES_TIME_AFTER; } break; } @@ -675,7 +676,7 @@ static NlaStrip *ctime_get_strip (ListBase *strips, short *side, float ctime) if (strip->extendmode != NLASTRIP_EXTEND_NOTHING) estrip= strip; - *side= NES_TIME_AFTER; + side= NES_TIME_AFTER; break; } @@ -683,40 +684,11 @@ static NlaStrip *ctime_get_strip (ListBase *strips, short *side, float ctime) } } - /* return the matching strip found */ - return estrip; -} - -/* gets the strip active at the current time for a track for evaluation purposes */ -static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index, float ctime) -{ - ListBase *strips= &nlt->strips; - NlaStrip *strip, *estrip=NULL; - NlaEvalStrip *nes; - short side= 0; - - /* keep looping over hierarchy of strips until one which fits for the current time is found */ - while (strips->first) { - /* try to get the strip at this frame for this strip */ - strip= ctime_get_strip(strips, &side, ctime); - - /* if a strip was found, make this the new estrip, otherwise, stop trying */ - if (strip) { - /* set new estrip */ - estrip= strip; - - /* check children (only available if this is a meta-strip) for better match */ - strips= &strip->strips; - } - else - break; - } - /* check if a valid strip was found * - must not be muted (i.e. will have contribution */ if ((estrip == NULL) || (estrip->flag & NLASTRIP_FLAG_MUTED)) - return; + return NULL; /* if ctime was not within the boundaries of the strip, clamp! */ switch (side) { @@ -734,8 +706,8 @@ static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index */ // TODO: this sounds a bit hacky having a few isolated F-Curves stuck on some data it operates on... nlastrip_evaluate_controls(estrip, ctime); - if (estrip->influence <= 0.0f) // XXX is it useful to invert the strip? - return; + if (estrip->influence <= 0.0f) + return NULL; /* check if strip has valid data to evaluate, * and/or perform any additional type-specific actions @@ -744,12 +716,12 @@ static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index case NLASTRIP_TYPE_CLIP: /* clip must have some action to evaluate */ if (estrip->act == NULL) - return; + return NULL; break; case NLASTRIP_TYPE_TRANSITION: /* there must be strips to transition from and to (i.e. prev and next required) */ if (ELEM(NULL, estrip->prev, estrip->next)) - return; + return NULL; /* evaluate controls for the relevant extents of the bordering strips... */ nlastrip_evaluate_controls(estrip->prev, estrip->start); @@ -760,13 +732,15 @@ static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index /* add to list of strips we need to evaluate */ nes= MEM_callocN(sizeof(NlaEvalStrip), "NlaEvalStrip"); - nes->track= nlt; nes->strip= estrip; nes->strip_mode= side; nes->track_index= index; nes->strip_time= estrip->strip_time; - BLI_addtail(list, nes); + if (list) + BLI_addtail(list, nes); + + return nes; } /* ---------------------- */ @@ -897,6 +871,38 @@ static void nlaevalchan_accumulate (NlaEvalChannel *nec, NlaEvalStrip *nes, shor } } +/* accumulate the results of a temporary buffer with the results of the full-buffer */ +static void nlaevalchan_buffers_accumulate (ListBase *channels, ListBase *tmp_buffer, NlaEvalStrip *nes) +{ + NlaEvalChannel *nec, *necn, *necd; + + /* optimise - abort if no channels */ + if (tmp_buffer->first == NULL) + return; + + /* accumulate results in tmp_channels buffer to the accumulation buffer */ + for (nec= tmp_buffer->first; nec; nec= necn) { + /* get pointer to next channel in case we remove the current channel from the temp-buffer */ + necn= nec->next; + + /* try to find an existing matching channel for this setting in the accumulation buffer */ + necd= nlaevalchan_find_match(channels, &nec->ptr, nec->prop, nec->index); + + /* if there was a matching channel already in the buffer, accumulate to it, + * otherwise, add the current channel to the buffer for efficiency + */ + if (necd) + nlaevalchan_accumulate(necd, nes, 0, nec->value); + else { + BLI_remlink(tmp_buffer, nec); + BLI_addtail(channels, nec); + } + } + + /* free temp-channels that haven't been assimilated into the buffer */ + BLI_freelistN(tmp_buffer); +} + /* ---------------------- */ /* evaluate action-clip strip */ @@ -945,7 +951,6 @@ static void nlastrip_evaluate_actionclip (PointerRNA *ptr, ListBase *channels, N static void nlastrip_evaluate_transition (PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes) { ListBase tmp_channels = {NULL, NULL}; - NlaEvalChannel *nec, *necn, *necd; NlaEvalStrip tmp_nes; NlaStrip *s1, *s2; @@ -986,38 +991,51 @@ static void nlastrip_evaluate_transition (PointerRNA *ptr, ListBase *channels, N nlastrip_evaluate_actionclip(ptr, &tmp_channels, &tmp_nes); - /* optimise - abort if no channels */ - if (tmp_channels.first == NULL) - return; - - - /* accumulate results in tmp_channels buffer to the accumulation buffer */ - for (nec= tmp_channels.first; nec; nec= necn) { - /* get pointer to next channel in case we remove the current channel from the temp-buffer */ - necn= nec->next; - - /* try to find an existing matching channel for this setting in the accumulation buffer */ - necd= nlaevalchan_find_match(channels, &nec->ptr, nec->prop, nec->index); - - /* if there was a matching channel already in the buffer, accumulate to it, - * otherwise, add the current channel to the buffer for efficiency - */ - if (necd) - nlaevalchan_accumulate(necd, nes, 0, nec->value); - else { - BLI_remlink(&tmp_channels, nec); - BLI_addtail(channels, nec); - } - } - - /* free temp-channels that haven't been assimilated into the buffer */ - BLI_freelistN(&tmp_channels); + /* assumulate temp-buffer and full-buffer, using the 'real' strip */ + nlaevalchan_buffers_accumulate(channels, &tmp_channels, nes); } +/* evaluate meta-strip */ +static void nlastrip_evaluate_meta (PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes) +{ + ListBase tmp_channels = {NULL, NULL}; + NlaStrip *strip= nes->strip; + NlaEvalStrip *tmp_nes; + float evaltime; + + /* meta-strip was calculated normally to have some time to be evaluated at + * and here we 'look inside' the meta strip, treating it as a decorated window to + * it's child strips, which get evaluated as if they were some tracks on a strip + * (but with some extra modifiers to apply). + * + * NOTE: keep this in sync with animsys_evaluate_nla() + */ + + /* find the child-strip to evaluate */ + evaltime= (nes->strip_time * (strip->end - strip->start)) + strip->start; + tmp_nes= nlastrips_ctime_get_strip(NULL, &strip->strips, -1, evaltime); + if (tmp_nes == NULL) + return; + + /* evaluate child-strip into tmp_channels buffer before accumulating + * in the accumulation buffer + */ + // TODO: need to supply overriding modifiers which will get applied over the top of these + nlastrip_evaluate(ptr, &tmp_channels, tmp_nes); + + /* assumulate temp-buffer and full-buffer, using the 'real' strip */ + nlaevalchan_buffers_accumulate(channels, &tmp_channels, nes); + + /* free temp eval-strip */ + MEM_freeN(tmp_nes); +} + + /* evaluates the given evaluation strip */ -static void nlastrip_evaluate (PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes) +void nlastrip_evaluate (PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes) { /* actions to take depend on the type of strip */ + // TODO: add 'modifiers' tag to chain switch (nes->strip->type) { case NLASTRIP_TYPE_CLIP: /* action-clip */ nlastrip_evaluate_actionclip(ptr, channels, nes); @@ -1025,11 +1043,14 @@ static void nlastrip_evaluate (PointerRNA *ptr, ListBase *channels, NlaEvalStrip case NLASTRIP_TYPE_TRANSITION: /* transition */ nlastrip_evaluate_transition(ptr, channels, nes); break; + case NLASTRIP_TYPE_META: /* meta */ + nlastrip_evaluate_meta(ptr, channels, nes); + break; } } /* write the accumulated settings to */ -static void nladata_flush_channels (ListBase *channels) +void nladata_flush_channels (ListBase *channels) { NlaEvalChannel *nec; @@ -1104,7 +1125,8 @@ static void animsys_evaluate_nla (PointerRNA *ptr, AnimData *adt, float ctime) continue; /* otherwise, get strip to evaluate for this channel */ - nlatrack_ctime_get_strip(&estrips, nlt, track_index, ctime); + nes= nlastrips_ctime_get_strip(&estrips, &nlt->strips, track_index, ctime); + if (nes) nes->track= nlt; } /* only continue if there are strips to evaluate */ diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 4dce9aebe24..511623f46fc 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -452,7 +452,7 @@ static float nlastrip_get_frame_transition (NlaStrip *strip, float cframe, short float nlastrip_get_frame (NlaStrip *strip, float cframe, short mode) { switch (strip->type) { - case NLASTRIP_TYPE_META: /* meta (is just a container for other strips, so shouldn't use the action-clip method) */ + case NLASTRIP_TYPE_META: /* meta - for now, does the same as transition (is really just an empty container) */ case NLASTRIP_TYPE_TRANSITION: /* transition */ return nlastrip_get_frame_transition(strip, cframe, mode); diff --git a/source/blender/blenkernel/nla_private.h b/source/blender/blenkernel/nla_private.h index 1514a79f03b..016eaedfe4c 100644 --- a/source/blender/blenkernel/nla_private.h +++ b/source/blender/blenkernel/nla_private.h @@ -75,5 +75,11 @@ typedef struct NlaEvalChannel { /* convert from strip time <-> global time */ float nlastrip_get_frame(NlaStrip *strip, float cframe, short mode); +/* --------------- NLA Evaluation (very-private stuff) ----------------------- */ +/* these functions are only defined here to avoid problems with the order in which they get defined... */ + +NlaEvalStrip *nlastrips_ctime_get_strip(ListBase *list, ListBase *strips, short index, float ctime); +void nlastrip_evaluate(PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes); +void nladata_flush_channels(ListBase *channels); #endif // NLA_PRIVATE From f8c344bd17e09f21b5f022f65016fc13a7aa1d69 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 7 Jul 2009 12:17:06 +0000 Subject: [PATCH 099/114] NLA SoC: Meta Strips + F-Modifiers F-Modifiers now work on 'all' types of NLA Strip. To get them working on Meta-strips, F-Modifiers on the Meta strip must be applied on top of those for child strips. For now, this is done by joining the lists of modifiers, and evaluating the joined list. Currently, Transitions don't work that great with F-Modifiers yet (only the endpoints get evaluated with the F-Modifiers). Solving this is for another time... --- source/blender/blenkernel/intern/anim_sys.c | 106 +++++++++++++++++--- source/blender/blenkernel/nla_private.h | 2 +- 2 files changed, 91 insertions(+), 17 deletions(-) diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 0aadb1825ad..1037b2fd15d 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -903,17 +903,76 @@ static void nlaevalchan_buffers_accumulate (ListBase *channels, ListBase *tmp_bu BLI_freelistN(tmp_buffer); } +/* ---------------------- */ +/* F-Modifier stack joining/separation utilities - should we generalise these for BLI_listbase.h interface? */ + +/* Temporarily join two lists of modifiers together, storing the result in a third list */ +static void nlaeval_fmodifiers_join_stacks (ListBase *result, ListBase *list1, ListBase *list2) +{ + FModifier *fcm1, *fcm2; + + /* if list1 is invalid... */ + if ELEM(NULL, list1, list1->first) { + if (list2 && list2->first) { + result->first= list2->first; + result->last= list2->last; + } + } + /* if list 2 is invalid... */ + else if ELEM(NULL, list2, list2->first) { + result->first= list1->first; + result->last= list1->last; + } + else { + /* list1 should be added first, and list2 second, with the endpoints of these being the endpoints for result + * - the original lists must be left unchanged though, as we need that fact for restoring + */ + result->first= list1->first; + result->last= list2->last; + + fcm1= list1->last; + fcm2= list2->first; + + fcm1->next= fcm2; + fcm2->prev= fcm1; + } +} + +/* Split two temporary lists of modifiers */ +static void nlaeval_fmodifiers_split_stacks (ListBase *list1, ListBase *list2) +{ + FModifier *fcm1, *fcm2; + + /* if list1/2 is invalid... just skip */ + if ELEM(NULL, list1, list2) + return; + if ELEM(NULL, list1->first, list2->first) + return; + + /* get endpoints */ + fcm1= list1->last; + fcm2= list2->first; + + /* clear their links */ + fcm1->next= NULL; + fcm2->prev= NULL; +} + /* ---------------------- */ /* evaluate action-clip strip */ -static void nlastrip_evaluate_actionclip (PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes) +static void nlastrip_evaluate_actionclip (PointerRNA *ptr, ListBase *channels, ListBase *modifiers, NlaEvalStrip *nes) { + ListBase tmp_modifiers = {NULL, NULL}; NlaStrip *strip= nes->strip; FCurve *fcu; float evaltime; + /* join this strip's modifiers to the parent's modifiers (own modifiers first) */ + nlaeval_fmodifiers_join_stacks(&tmp_modifiers, &strip->modifiers, modifiers); + /* evaluate strip's modifiers which modify time to evaluate the base curves at */ - evaltime= evaluate_time_fmodifiers(&strip->modifiers, NULL, 0.0f, strip->strip_time); + evaltime= evaluate_time_fmodifiers(&tmp_modifiers, NULL, 0.0f, strip->strip_time); /* evaluate all the F-Curves in the action, saving the relevant pointers to data that will need to be used */ for (fcu= strip->act->curves.first; fcu; fcu= fcu->next) { @@ -935,7 +994,7 @@ static void nlastrip_evaluate_actionclip (PointerRNA *ptr, ListBase *channels, N /* apply strip's F-Curve Modifiers on this value * NOTE: we apply the strip's original evaluation time not the modified one (as per standard F-Curve eval) */ - evaluate_value_fmodifiers(&strip->modifiers, fcu, &value, strip->strip_time); + evaluate_value_fmodifiers(&tmp_modifiers, fcu, &value, strip->strip_time); /* get an NLA evaluation channel to work with, and accumulate the evaluated value with the value(s) @@ -945,15 +1004,22 @@ static void nlastrip_evaluate_actionclip (PointerRNA *ptr, ListBase *channels, N if (nec) nlaevalchan_accumulate(nec, nes, newChan, value); } + + /* unlink this strip's modifiers from the parent's modifiers again */ + nlaeval_fmodifiers_split_stacks(&strip->modifiers, modifiers); } /* evaluate transition strip */ -static void nlastrip_evaluate_transition (PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes) +static void nlastrip_evaluate_transition (PointerRNA *ptr, ListBase *channels, ListBase *modifiers, NlaEvalStrip *nes) { ListBase tmp_channels = {NULL, NULL}; + ListBase tmp_modifiers = {NULL, NULL}; NlaEvalStrip tmp_nes; NlaStrip *s1, *s2; + /* join this strip's modifiers to the parent's modifiers (own modifiers first) */ + nlaeval_fmodifiers_join_stacks(&tmp_modifiers, &nes->strip->modifiers, modifiers); + /* get the two strips to operate on * - we use the endpoints of the strips directly flanking our strip * using these as the endpoints of the transition (destination and source) @@ -980,25 +1046,30 @@ static void nlastrip_evaluate_transition (PointerRNA *ptr, ListBase *channels, N tmp_nes= *nes; /* evaluate these strips into a temp-buffer (tmp_channels) */ + // FIXME: modifier evalation here needs some work... /* first strip */ tmp_nes.strip_mode= NES_TIME_TRANSITION_START; tmp_nes.strip= s1; - nlastrip_evaluate_actionclip(ptr, &tmp_channels, &tmp_nes); + nlastrip_evaluate_actionclip(ptr, &tmp_channels, &tmp_modifiers, &tmp_nes); /* second strip */ tmp_nes.strip_mode= NES_TIME_TRANSITION_END; tmp_nes.strip= s2; - nlastrip_evaluate_actionclip(ptr, &tmp_channels, &tmp_nes); + nlastrip_evaluate_actionclip(ptr, &tmp_channels, &tmp_modifiers, &tmp_nes); /* assumulate temp-buffer and full-buffer, using the 'real' strip */ nlaevalchan_buffers_accumulate(channels, &tmp_channels, nes); + + /* unlink this strip's modifiers from the parent's modifiers again */ + nlaeval_fmodifiers_split_stacks(&nes->strip->modifiers, modifiers); } /* evaluate meta-strip */ -static void nlastrip_evaluate_meta (PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes) +static void nlastrip_evaluate_meta (PointerRNA *ptr, ListBase *channels, ListBase *modifiers, NlaEvalStrip *nes) { ListBase tmp_channels = {NULL, NULL}; + ListBase tmp_modifiers = {NULL, NULL}; NlaStrip *strip= nes->strip; NlaEvalStrip *tmp_nes; float evaltime; @@ -1010,6 +1081,9 @@ static void nlastrip_evaluate_meta (PointerRNA *ptr, ListBase *channels, NlaEval * * NOTE: keep this in sync with animsys_evaluate_nla() */ + + /* join this strip's modifiers to the parent's modifiers (own modifiers first) */ + nlaeval_fmodifiers_join_stacks(&tmp_modifiers, &strip->modifiers, modifiers); /* find the child-strip to evaluate */ evaltime= (nes->strip_time * (strip->end - strip->start)) + strip->start; @@ -1020,31 +1094,31 @@ static void nlastrip_evaluate_meta (PointerRNA *ptr, ListBase *channels, NlaEval /* evaluate child-strip into tmp_channels buffer before accumulating * in the accumulation buffer */ - // TODO: need to supply overriding modifiers which will get applied over the top of these - nlastrip_evaluate(ptr, &tmp_channels, tmp_nes); + nlastrip_evaluate(ptr, &tmp_channels, &tmp_modifiers, tmp_nes); /* assumulate temp-buffer and full-buffer, using the 'real' strip */ nlaevalchan_buffers_accumulate(channels, &tmp_channels, nes); /* free temp eval-strip */ MEM_freeN(tmp_nes); + + /* unlink this strip's modifiers from the parent's modifiers again */ + nlaeval_fmodifiers_split_stacks(&strip->modifiers, modifiers); } - /* evaluates the given evaluation strip */ -void nlastrip_evaluate (PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes) +void nlastrip_evaluate (PointerRNA *ptr, ListBase *channels, ListBase *modifiers, NlaEvalStrip *nes) { /* actions to take depend on the type of strip */ - // TODO: add 'modifiers' tag to chain switch (nes->strip->type) { case NLASTRIP_TYPE_CLIP: /* action-clip */ - nlastrip_evaluate_actionclip(ptr, channels, nes); + nlastrip_evaluate_actionclip(ptr, channels, modifiers, nes); break; case NLASTRIP_TYPE_TRANSITION: /* transition */ - nlastrip_evaluate_transition(ptr, channels, nes); + nlastrip_evaluate_transition(ptr, channels, modifiers, nes); break; case NLASTRIP_TYPE_META: /* meta */ - nlastrip_evaluate_meta(ptr, channels, nes); + nlastrip_evaluate_meta(ptr, channels, modifiers, nes); break; } } @@ -1136,7 +1210,7 @@ static void animsys_evaluate_nla (PointerRNA *ptr, AnimData *adt, float ctime) /* 2. for each strip, evaluate then accumulate on top of existing channels, but don't set values yet */ for (nes= estrips.first; nes; nes= nes->next) - nlastrip_evaluate(ptr, &echannels, nes); + nlastrip_evaluate(ptr, &echannels, NULL, nes); /* 3. flush effects of accumulating channels in NLA to the actual data they affect */ nladata_flush_channels(&echannels); diff --git a/source/blender/blenkernel/nla_private.h b/source/blender/blenkernel/nla_private.h index 016eaedfe4c..df7ffaa3064 100644 --- a/source/blender/blenkernel/nla_private.h +++ b/source/blender/blenkernel/nla_private.h @@ -79,7 +79,7 @@ float nlastrip_get_frame(NlaStrip *strip, float cframe, short mode); /* these functions are only defined here to avoid problems with the order in which they get defined... */ NlaEvalStrip *nlastrips_ctime_get_strip(ListBase *list, ListBase *strips, short index, float ctime); -void nlastrip_evaluate(PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes); +void nlastrip_evaluate(PointerRNA *ptr, ListBase *channels, ListBase *modifiers, NlaEvalStrip *nes); void nladata_flush_channels(ListBase *channels); #endif // NLA_PRIVATE From 823bf891a113cc0d1893706cf374aceec2715b8f Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 7 Jul 2009 23:33:39 +0000 Subject: [PATCH 100/114] NLA SoC: Clarifying the error message for adding transitions NOTE: transition strips can only be added between two selected action-clips that have a gap (but no other strips) between them, and are in the same track. --- source/blender/editors/space_nla/nla_edit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index d663b76d5fe..0198a66949e 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -432,7 +432,7 @@ static int nlaedit_add_transition_exec (bContext *C, wmOperator *op) return OPERATOR_FINISHED; } else { - BKE_report(op->reports, RPT_ERROR, "Needs at least a pair of adjacent selected strips."); + BKE_report(op->reports, RPT_ERROR, "Needs at least a pair of adjacent selected strips with a gap between them."); return OPERATOR_CANCELLED; } } From be5293d3ad38ba5f9f32ac8585d012bc44a9e684 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Wed, 8 Jul 2009 05:00:10 +0000 Subject: [PATCH 101/114] NLA SoC: Influence/Time properties for strips can now be animated * These settings can now be edited + keyframed (using IKEY over the button only for now... other cases will fail) * Reshuffled some of the keyframing code to make this sort of thing easier to do. Also, restored corrections for NLA-mapping when inserting/removing keyframes. TODOS: * animation editors don't show these keyframes yet * the buttons don't change colour yet to reflect this state. How to do this efficiently? * allow keyframing of these in more places * more robust UI handling for this. --- source/blender/blenkernel/BKE_nla.h | 4 + source/blender/blenkernel/intern/nla.c | 52 ++++ source/blender/editors/animation/keyframing.c | 237 +++++++++++------- .../blender/editors/include/ED_keyframing.h | 13 + .../blender/editors/space_nla/nla_buttons.c | 17 +- source/blender/makesrna/intern/rna_nla.c | 36 ++- 6 files changed, 255 insertions(+), 104 deletions(-) diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index 5cb967c9c59..7fdff7e41f7 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -80,8 +80,12 @@ short BKE_nlatrack_add_strip(struct NlaTrack *nlt, struct NlaStrip *strip); /* ............ */ struct NlaStrip *BKE_nlastrip_find_active(struct NlaTrack *nlt); + short BKE_nlastrip_within_bounds(struct NlaStrip *strip, float min, float max); +void BKE_nlastrip_validate_fcurves(struct NlaStrip *strip); + +/* ............ */ void BKE_nla_action_pushdown(struct AnimData *adt); diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 511623f46fc..217444d16d2 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -1049,6 +1049,58 @@ short nlastrip_is_first (AnimData *adt, NlaStrip *strip) /* should be first now */ return 1; } + +/* Validate the NLA-Strips 'control' F-Curves based on the flags set*/ +void BKE_nlastrip_validate_fcurves (NlaStrip *strip) +{ + FCurve *fcu; + + /* sanity checks */ + if (strip == NULL) + return; + + /* if controlling influence... */ + if (strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) { + /* try to get F-Curve */ + fcu= list_find_fcurve(&strip->fcurves, "influence", 0); + + /* add one if not found */ + if (fcu == NULL) { + /* make new F-Curve */ + fcu= MEM_callocN(sizeof(FCurve), "NlaStrip FCurve"); + BLI_addtail(&strip->fcurves, fcu); + + /* set default flags */ + fcu->flag = (FCURVE_VISIBLE|FCURVE_AUTO_HANDLES|FCURVE_SELECTED); + + /* store path - make copy, and store that */ + fcu->rna_path= BLI_strdupn("influence", 9); + + // TODO: insert a few keyframes to ensure default behaviour? + } + } + + /* if controlling time... */ + if (strip->flag & NLASTRIP_FLAG_USR_TIME) { + /* try to get F-Curve */ + fcu= list_find_fcurve(&strip->fcurves, "strip_time", 0); + + /* add one if not found */ + if (fcu == NULL) { + /* make new F-Curve */ + fcu= MEM_callocN(sizeof(FCurve), "NlaStrip FCurve"); + BLI_addtail(&strip->fcurves, fcu); + + /* set default flags */ + fcu->flag = (FCURVE_VISIBLE|FCURVE_AUTO_HANDLES|FCURVE_SELECTED); + + /* store path - make copy, and store that */ + fcu->rna_path= BLI_strdupn("strip_time", 10); + + // TODO: insert a few keyframes to ensure default behaviour? + } + } +} /* Tools ------------------------------------------- */ diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index 331e2d0894e..ac195f42f03 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -54,6 +54,7 @@ #include "BKE_action.h" #include "BKE_constraint.h" #include "BKE_fcurve.h" +#include "BKE_nla.h" #include "BKE_global.h" #include "BKE_utildefines.h" #include "BKE_context.h" @@ -722,9 +723,119 @@ static float visualkey_get_value (PointerRNA *ptr, PropertyRNA *prop, int array_ /* ------------------------- Insert Key API ------------------------- */ +/* Secondary Keyframing API call: + * Use this when validation of necessary animation data is not necessary, since an RNA-pointer to the necessary + * data being keyframed, and a pointer to the F-Curve to use have both been provided. + * + * The flag argument is used for special settings that alter the behaviour of + * the keyframe insertion. These include the 'visual' keyframing modes, quick refresh, + * and extra keyframe filtering. + */ +short insert_keyframe_direct (PointerRNA ptr, PropertyRNA *prop, FCurve *fcu, float cfra, short flag) +{ + float curval= 0.0f; + + /* no F-Curve to add keyframe to? */ + if (fcu == NULL) { + printf("ERROR: no F-Curve to add keyframes to \n"); + return 0; + } + + /* if no property given yet, try to validate from F-Curve info */ + if ((ptr.id.data == NULL) && (ptr.data==NULL)) { + printf("ERROR: no RNA-pointer available to retrieve values for keyframing from\n"); + return 0; + } + if (prop == NULL) { + PointerRNA tmp_ptr; + + /* try to get property we should be affecting */ + if ((RNA_path_resolve(&ptr, fcu->rna_path, &tmp_ptr, &prop) == 0) || (prop == NULL)) { + /* property not found... */ + char *idname= (ptr.id.data) ? ((ID *)ptr.id.data)->name : ""; + + printf("Insert Key: Could not insert keyframe, as RNA Path is invalid for the given ID (ID = %s, Path = %s)\n", idname, fcu->rna_path); + return 0; + } + else { + /* property found, so overwrite 'ptr' to make later code easier */ + ptr= tmp_ptr; + } + } + + /* set additional flags for the F-Curve (i.e. only integer values) */ + fcu->flag &= ~(FCURVE_INT_VALUES|FCURVE_DISCRETE_VALUES); + switch (RNA_property_type(prop)) { + case PROP_FLOAT: + /* do nothing */ + break; + case PROP_INT: + /* do integer (only 'whole' numbers) interpolation between all points */ + fcu->flag |= FCURVE_INT_VALUES; + break; + default: + /* do 'discrete' (i.e. enum, boolean values which cannot take any intermediate + * values at all) interpolation between all points + * - however, we must also ensure that evaluated values are only integers still + */ + fcu->flag |= (FCURVE_DISCRETE_VALUES|FCURVE_INT_VALUES); + break; + } + + /* obtain value to give keyframe */ + if ( (flag & INSERTKEY_MATRIX) && + (visualkey_can_use(&ptr, prop)) ) + { + /* visual-keying is only available for object and pchan datablocks, as + * it works by keyframing using a value extracted from the final matrix + * instead of using the kt system to extract a value. + */ + curval= visualkey_get_value(&ptr, prop, fcu->array_index); + } + else { + /* read value from system */ + curval= setting_get_rna_value(&ptr, prop, fcu->array_index); + } + + /* only insert keyframes where they are needed */ + if (flag & INSERTKEY_NEEDED) { + short insert_mode; + + /* check whether this curve really needs a new keyframe */ + insert_mode= new_key_needed(fcu, cfra, curval); + + /* insert new keyframe at current frame */ + if (insert_mode) + insert_vert_fcurve(fcu, cfra, curval, (flag & INSERTKEY_FAST)); + + /* delete keyframe immediately before/after newly added */ + switch (insert_mode) { + case KEYNEEDED_DELPREV: + delete_fcurve_key(fcu, fcu->totvert-2, 1); + break; + case KEYNEEDED_DELNEXT: + delete_fcurve_key(fcu, 1, 1); + break; + } + + /* only return success if keyframe added */ + if (insert_mode) + return 1; + } + else { + /* just insert keyframe */ + insert_vert_fcurve(fcu, cfra, curval, (flag & INSERTKEY_FAST)); + + /* return success */ + return 1; + } + + /* failed */ + return 0; +} + /* Main Keyframing API call: - * Use this when validation of necessary animation data isn't necessary as it - * already exists. It will insert a keyframe using the current value being keyframed. + * Use this when validation of necessary animation data is necessary, since it may not exist yet. * * The flag argument is used for special settings that alter the behaviour of * the keyframe insertion. These include the 'visual' keyframing modes, quick refresh, @@ -744,102 +855,31 @@ short insert_keyframe (ID *id, bAction *act, const char group[], const char rna_ } /* get F-Curve - if no action is provided, keyframe to the default one attached to this ID-block */ - if (act == NULL) + if (act == NULL) { + AnimData *adt= BKE_animdata_from_id(id); + + /* get action to add F-Curve+keyframe to */ act= verify_adt_action(id, 1); + + /* apply NLA-mapping to frame to use (if applicable) */ + cfra= BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP); + } fcu= verify_fcurve(act, group, rna_path, array_index, 1); - /* only continue if we have an F-Curve to add keyframe to */ - if (fcu) { - float curval= 0.0f; + /* apply special time tweaking */ + // XXX check on this stuff... + if (GS(id->name) == ID_OB) { + //Object *ob= (Object *)id; - /* set additional flags for the F-Curve (i.e. only integer values) */ - fcu->flag &= ~(FCURVE_INT_VALUES|FCURVE_DISCRETE_VALUES); - switch (RNA_property_type(prop)) { - case PROP_FLOAT: - /* do nothing */ - break; - case PROP_INT: - /* do integer (only 'whole' numbers) interpolation between all points */ - fcu->flag |= FCURVE_INT_VALUES; - break; - default: - /* do 'discrete' (i.e. enum, boolean values which cannot take any intermediate - * values at all) interpolation between all points - * - however, we must also ensure that evaluated values are only integers still - */ - fcu->flag |= (FCURVE_DISCRETE_VALUES|FCURVE_INT_VALUES); - break; - } - - /* apply special time tweaking */ - // XXX check on this stuff... - if (GS(id->name) == ID_OB) { - //Object *ob= (Object *)id; - - /* apply NLA-scaling (if applicable) */ - //cfra= get_action_frame(ob, cfra); - - /* ancient time-offset cruft */ - //if ( (ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)) ) { - // /* actually frametofloat calc again! */ - // cfra-= give_timeoffset(ob)*scene->r.framelen; - //} - } - - /* obtain value to give keyframe */ - if ( (flag & INSERTKEY_MATRIX) && - (visualkey_can_use(&ptr, prop)) ) - { - /* visual-keying is only available for object and pchan datablocks, as - * it works by keyframing using a value extracted from the final matrix - * instead of using the kt system to extract a value. - */ - curval= visualkey_get_value(&ptr, prop, array_index); - } - else { - /* read value from system */ - curval= setting_get_rna_value(&ptr, prop, array_index); - } - - /* only insert keyframes where they are needed */ - if (flag & INSERTKEY_NEEDED) { - short insert_mode; - - /* check whether this curve really needs a new keyframe */ - insert_mode= new_key_needed(fcu, cfra, curval); - - /* insert new keyframe at current frame */ - if (insert_mode) - insert_vert_fcurve(fcu, cfra, curval, (flag & INSERTKEY_FAST)); - - /* delete keyframe immediately before/after newly added */ - switch (insert_mode) { - case KEYNEEDED_DELPREV: - delete_fcurve_key(fcu, fcu->totvert-2, 1); - break; - case KEYNEEDED_DELNEXT: - delete_fcurve_key(fcu, 1, 1); - break; - } - - /* only return success if keyframe added */ - if (insert_mode) - return 1; - } - else { - /* just insert keyframe */ - insert_vert_fcurve(fcu, cfra, curval, (flag & INSERTKEY_FAST)); - - /* return success */ - return 1; - } + /* ancient time-offset cruft */ + //if ( (ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)) ) { + // /* actually frametofloat calc again! */ + // cfra-= give_timeoffset(ob)*scene->r.framelen; + //} } - /* no F-Curve to add keyframes to */ - printf("ERROR: no F-Curve to add keyframes to \n"); - - /* return failure */ - return 0; + /* insert keyframe */ + return insert_keyframe_direct(ptr, prop, fcu, cfra, flag); } /* ************************************************** */ @@ -864,6 +904,9 @@ short delete_keyframe (ID *id, bAction *act, const char group[], const char rna_ /* if no action is provided, use the default one attached to this ID-block */ AnimData *adt= BKE_animdata_from_id(id); act= adt->action; + + /* apply NLA-mapping to frame to use (if applicable) */ + cfra= BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP); } /* we don't check the validity of the path here yet, but it should be ok... */ fcu= verify_fcurve(act, group, rna_path, array_index, 0); @@ -877,9 +920,6 @@ short delete_keyframe (ID *id, bAction *act, const char group[], const char rna_ if (GS(id->name) == ID_OB) { //Object *ob= (Object *)id; - /* apply NLA-scaling (if applicable) */ - // cfra= get_action_frame(ob, cfra); - /* ancient time-offset cruft */ //if ( (ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)) ) { // /* actually frametofloat calc again! */ @@ -1266,6 +1306,13 @@ static int insert_key_button_exec (bContext *C, wmOperator *op) MEM_freeN(path); } + else if (ptr.type == &RNA_NlaStrip) { + /* handle special vars for NLA-strips */ + NlaStrip *strip= (NlaStrip *)ptr.data; + FCurve *fcu= list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), 0); + + success+= insert_keyframe_direct(ptr, prop, fcu, cfra, 0); + } else { if (G.f & G_DEBUG) printf("Button Insert-Key: no path to property \n"); diff --git a/source/blender/editors/include/ED_keyframing.h b/source/blender/editors/include/ED_keyframing.h index 9d063910aa9..ffebb42ce99 100644 --- a/source/blender/editors/include/ED_keyframing.h +++ b/source/blender/editors/include/ED_keyframing.h @@ -43,6 +43,9 @@ struct bConstraint; struct bContext; struct wmOperatorType; +struct PointerRNA; +struct PropertyRNA; + /* ************ Keyframing Management **************** */ /* Get (or add relevant data to be able to do so) the Active Action for the given @@ -69,6 +72,16 @@ int insert_bezt_fcurve(struct FCurve *fcu, struct BezTriple *bezt); */ void insert_vert_fcurve(struct FCurve *fcu, float x, float y, short flag); +/* -------- */ + +/* Secondary Keyframing API calls: + * Use this to insert a keyframe using the current value being keyframed, in the + * nominated F-Curve (no creation of animation data performed). Returns success. + */ +short insert_keyframe_direct(struct PointerRNA ptr, struct PropertyRNA *prop, struct FCurve *fcu, float cfra, short flag); + + + /* -------- */ /* Main Keyframing API calls: diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c index 38ac59cbc9e..d09cc6a1e53 100644 --- a/source/blender/editors/space_nla/nla_buttons.c +++ b/source/blender/editors/space_nla/nla_buttons.c @@ -271,7 +271,7 @@ static void nla_panel_actclip(const bContext *C, Panel *pa) uiItemR(row, NULL, ICON_ACTION, &strip_ptr, "action", 0, 0, 0); /* action extents */ - // XXX custom names were used here... probably not necessary in future? + // XXX custom names were used here (to avoid the prefixes)... probably not necessary in future? column= uiLayoutColumn(layout, 1); uiItemL(column, "Action Extents:", 0); uiItemR(column, "Start Frame", 0, &strip_ptr, "action_start_frame", 0, 0, 0); @@ -289,7 +289,7 @@ static void nla_panel_evaluation(const bContext *C, Panel *pa) { PointerRNA strip_ptr; uiLayout *layout= pa->layout; - uiLayout *column; + uiLayout *column, *subcolumn; uiBlock *block; /* check context and also validity of pointer */ @@ -300,14 +300,19 @@ static void nla_panel_evaluation(const bContext *C, Panel *pa) uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL); column= uiLayoutColumn(layout, 1); - uiLayoutSetEnabled(column, 0); // XXX for now, don't allow user to edit uiItemR(column, NULL, 0, &strip_ptr, "animated_influence", 0, 0, 0); - uiItemR(column, NULL, 0, &strip_ptr, "influence", 0, 0, 0); + subcolumn= uiLayoutColumn(column, 1); + uiLayoutSetEnabled(subcolumn, RNA_boolean_get(&strip_ptr, "animated_influence")); + uiItemR(subcolumn, NULL, 0, &strip_ptr, "influence", 0, 0, 0); + + column= uiLayoutColumn(layout, 1); - uiLayoutSetEnabled(column, 0); // XXX for now, don't allow user to edit uiItemR(column, NULL, 0, &strip_ptr, "animated_time", 0, 0, 0); - uiItemR(column, NULL, 0, &strip_ptr, "strip_time", 0, 0, 0); + + subcolumn= uiLayoutColumn(column, 1); + uiLayoutSetEnabled(subcolumn, RNA_boolean_get(&strip_ptr, "animated_time")); + uiItemR(subcolumn, NULL, 0, &strip_ptr, "strip_time", 0, 0, 0); } /* F-Modifiers for active NLA-Strip */ diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c index b0149d29e69..219feaad09b 100644 --- a/source/blender/makesrna/intern/rna_nla.c +++ b/source/blender/makesrna/intern/rna_nla.c @@ -40,6 +40,9 @@ #include #include +/* needed for some of the validation stuff... */ +#include "BKE_nla.h" + /* temp constant defined for these funcs only... */ #define NLASTRIP_MIN_LEN_THRESH 0.1f @@ -196,6 +199,32 @@ static void rna_NlaStrip_action_end_frame_set(PointerRNA *ptr, float value) data->actend= value; } +static void rna_NlaStrip_animated_influence_set(PointerRNA *ptr, int value) +{ + NlaStrip *data= (NlaStrip*)ptr->data; + + if (value) { + /* set the flag, then make sure a curve for this exists */ + data->flag |= NLASTRIP_FLAG_USR_INFLUENCE; + BKE_nlastrip_validate_fcurves(data); + } + else + data->flag &= ~NLASTRIP_FLAG_USR_INFLUENCE; +} + +static void rna_NlaStrip_animated_time_set(PointerRNA *ptr, int value) +{ + NlaStrip *data= (NlaStrip*)ptr->data; + + if (value) { + /* set the flag, then make sure a curve for this exists */ + data->flag |= NLASTRIP_FLAG_USR_TIME; + BKE_nlastrip_validate_fcurves(data); + } + else + data->flag &= ~NLASTRIP_FLAG_USR_TIME; +} + #else void rna_def_nlastrip(BlenderRNA *brna) @@ -321,14 +350,15 @@ void rna_def_nlastrip(BlenderRNA *brna) prop= RNA_def_property(srna, "strip_time", PROP_FLOAT, PROP_NONE); RNA_def_property_ui_text(prop, "Strip Time", "Frame of referenced Action to evaluate."); + // TODO: should the animated_influence/time settings be animatable themselves? prop= RNA_def_property(srna, "animated_influence", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); // XXX for now, not editable RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_USR_INFLUENCE); + RNA_def_property_boolean_funcs(prop, NULL, "rna_NlaStrip_animated_influence_set"); RNA_def_property_ui_text(prop, "Animated Influence", "Influence setting is controlled by an F-Curve rather than automatically determined."); prop= RNA_def_property(srna, "animated_time", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); // XXX for now, not editable - RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_USR_INFLUENCE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_USR_TIME); + RNA_def_property_boolean_funcs(prop, NULL, "rna_NlaStrip_animated_time_set"); RNA_def_property_ui_text(prop, "Animated Strip Time", "Strip time is controlled by an F-Curve rather than automatically determined."); /* settings */ From 665938191df7e831ba22f101b00ab9b99bdde654 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Wed, 8 Jul 2009 06:32:52 +0000 Subject: [PATCH 102/114] NLA SoC: Minor UI-Tweaks * When influence/time for NLA-strips are animated, settings in the other panels which used to control these are now greyed out to show that they won't have any impact over the result. * NKey panel for Graph Editor now opens on Right-Hand Side, just like for NLA Editor. The small sub-region above the Channels region was too troublesome to work with. --- source/blender/editors/space_graph/space_graph.c | 16 ++++++++-------- source/blender/editors/space_nla/nla_buttons.c | 12 ++++++++---- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c index b17861dc679..2f3700bc733 100644 --- a/source/blender/editors/space_graph/space_graph.c +++ b/source/blender/editors/space_graph/space_graph.c @@ -72,19 +72,19 @@ ARegion *graph_has_buttons_region(ScrArea *sa) if(ar->regiontype==RGN_TYPE_UI) return ar; - /* add subdiv level; after channel */ + /* add subdiv level; after main window */ for(ar= sa->regionbase.first; ar; ar= ar->next) - if(ar->regiontype==RGN_TYPE_CHANNELS) + if(ar->regiontype==RGN_TYPE_WINDOW) break; /* is error! */ if(ar==NULL) return NULL; - arnew= MEM_callocN(sizeof(ARegion), "buttons for view3d"); + arnew= MEM_callocN(sizeof(ARegion), "buttons for nla"); BLI_insertlinkafter(&sa->regionbase, ar, arnew); arnew->regiontype= RGN_TYPE_UI; - arnew->alignment= RGN_ALIGN_BOTTOM|RGN_SPLIT_PREV; + arnew->alignment= RGN_ALIGN_RIGHT; arnew->flag = RGN_FLAG_HIDDEN; @@ -117,7 +117,7 @@ static SpaceLink *graph_new(const bContext *C) ar->alignment= RGN_ALIGN_BOTTOM; /* channels */ - ar= MEM_callocN(sizeof(ARegion), "main area for graphedit"); + ar= MEM_callocN(sizeof(ARegion), "channels area for graphedit"); BLI_addtail(&sipo->regionbase, ar); ar->regiontype= RGN_TYPE_CHANNELS; @@ -126,11 +126,11 @@ static SpaceLink *graph_new(const bContext *C) ar->v2d.scroll = (V2D_SCROLL_RIGHT|V2D_SCROLL_BOTTOM); /* ui buttons */ - ar= MEM_callocN(sizeof(ARegion), "main area for graphedit"); + ar= MEM_callocN(sizeof(ARegion), "buttons area for graphedit"); BLI_addtail(&sipo->regionbase, ar); ar->regiontype= RGN_TYPE_UI; - ar->alignment= RGN_ALIGN_TOP|RGN_SPLIT_PREV; + ar->alignment= RGN_ALIGN_RIGHT; ar->flag = RGN_FLAG_HIDDEN; /* main area */ @@ -566,7 +566,7 @@ void ED_spacetype_ipo(void) /* regions: UI buttons */ art= MEM_callocN(sizeof(ARegionType), "spacetype graphedit region"); art->regionid = RGN_TYPE_UI; - art->minsizey= 200; + art->minsizex= 200; art->keymapflag= ED_KEYMAP_UI; art->listener= graph_region_listener; art->init= graph_buttons_area_init; diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c index d09cc6a1e53..c0a2b9476e3 100644 --- a/source/blender/editors/space_nla/nla_buttons.c +++ b/source/blender/editors/space_nla/nla_buttons.c @@ -236,14 +236,17 @@ static void nla_panel_properties(const bContext *C, Panel *pa) * - blend in/out can only be set when autoblending is off */ column= uiLayoutColumn(layout, 1); + uiLayoutSetActive(column, RNA_boolean_get(&strip_ptr, "animated_influence")==0); uiItemR(column, NULL, 0, &strip_ptr, "auto_blending", 0, 0, 0); // XXX as toggle? - subcol= uiLayoutColumn(column, 1); - uiLayoutSetActive(subcol, RNA_boolean_get(&strip_ptr, "auto_blending")==0); - uiItemR(subcol, NULL, 0, &strip_ptr, "blend_in", 0, 0, 0); - uiItemR(subcol, NULL, 0, &strip_ptr, "blend_out", 0, 0, 0); + + subcol= uiLayoutColumn(column, 1); + uiLayoutSetActive(subcol, RNA_boolean_get(&strip_ptr, "auto_blending")==0); + uiItemR(subcol, NULL, 0, &strip_ptr, "blend_in", 0, 0, 0); + uiItemR(subcol, NULL, 0, &strip_ptr, "blend_out", 0, 0, 0); /* settings */ column= uiLayoutColumn(layout, 1); + uiLayoutSetActive(column, !(RNA_boolean_get(&strip_ptr, "animated_influence") || RNA_boolean_get(&strip_ptr, "animated_time"))); uiItemL(column, "Playback Settings:", 0); uiItemR(column, NULL, 0, &strip_ptr, "muted", 0, 0, 0); uiItemR(column, NULL, 0, &strip_ptr, "reversed", 0, 0, 0); @@ -279,6 +282,7 @@ static void nla_panel_actclip(const bContext *C, Panel *pa) /* action usage */ column= uiLayoutColumn(layout, 1); + uiLayoutSetActive(column, RNA_boolean_get(&strip_ptr, "animated_time")==0); uiItemL(column, "Playback Settings:", 0); uiItemR(column, NULL, 0, &strip_ptr, "scale", 0, 0, 0); uiItemR(column, NULL, 0, &strip_ptr, "repeat", 0, 0, 0); From 5f5ddb00146884d28414811bc92311af56d55904 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Wed, 8 Jul 2009 12:30:09 +0000 Subject: [PATCH 103/114] NLA SoC: Little optimisation + Drawing bugfix * Text labels on NLA-Strips should now draw properly for most short-strips now. Previously, the padding on the text was a bit too extreme, so for very short strips (less than 4 frames or so), the text was often pushed down into the bottom-right corner of view. * Optimised the keyframe-highlighting code for buttons a bit. Replaced the custom linear-search with the binary-search used when inserting keyframes (and for the 3d-view keyframe-indicator). There should be some theoretical improvements due to this at least... --- source/blender/blenkernel/BKE_fcurve.h | 3 -- source/blender/blenkernel/intern/fcurve.c | 14 ------- source/blender/editors/animation/keyframing.c | 41 ++++++++++++------- .../blender/editors/include/ED_keyframing.h | 5 +++ .../editors/interface/interface_anim.c | 4 +- source/blender/editors/space_nla/nla_draw.c | 15 +++---- 6 files changed, 43 insertions(+), 39 deletions(-) diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h index 4dcb08dc0df..cda64c6b241 100644 --- a/source/blender/blenkernel/BKE_fcurve.h +++ b/source/blender/blenkernel/BKE_fcurve.h @@ -153,9 +153,6 @@ 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); -/* test if there is a keyframe at cfra */ -short on_keyframe_fcurve(struct FCurve *fcu, float cfra); - /* get the time extents for F-Curve */ void calc_fcurve_range(struct FCurve *fcu, float *min, float *max); diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 4c2ba61fc71..ebd94b94f8c 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -200,20 +200,6 @@ FCurve *list_find_fcurve (ListBase *list, const char rna_path[], const int array return NULL; } -short on_keyframe_fcurve(FCurve *fcu, float cfra) -{ - BezTriple *bezt; - unsigned i; - - bezt= fcu->bezt; - for (i=0; itotvert; i++, bezt++) { - if (IS_EQ(bezt->vec[1][0], cfra)) - return 1; - } - - return 0; -} - /* Calculate the extents of F-Curve's data */ void calc_fcurve_bounds (FCurve *fcu, float *xmin, float *xmax, float *ymin, float *ymax) { diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index ac195f42f03..dd4c4c23f1e 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -1430,6 +1430,31 @@ void ANIM_OT_delete_keyframe_button (wmOperatorType *ot) /* --------------- API/Per-Datablock Handling ------------------- */ +/* Checks if some F-Curve has a keyframe for a given frame */ +short fcurve_frame_has_keyframe (FCurve *fcu, float frame, short filter) +{ + /* quick sanity check */ + if (fcu == NULL) + return 0; + + /* we either include all regardless of muting, or only non-muted */ + if ((filter & ANIMFILTER_KEYS_MUTED) || (fcu->flag & FCURVE_MUTED)==0) { + short replace = -1; + int i = binarysearch_bezt_index(fcu->bezt, frame, fcu->totvert, &replace); + + /* binarysearch_bezt_index will set replace to be 0 or 1 + * - obviously, 1 represents a match + */ + if (replace) { + /* sanity check: 'i' may in rare cases exceed arraylen */ + if ((i >= 0) && (i < fcu->totvert)) + return 1; + } + } + + return 0; +} + /* Checks whether an Action has a keyframe for a given frame * Since we're only concerned whether a keyframe exists, we can simply loop until a match is found... */ @@ -1451,20 +1476,8 @@ short action_frame_has_keyframe (bAction *act, float frame, short filter) for (fcu= act->curves.first; fcu; fcu= fcu->next) { /* only check if there are keyframes (currently only of type BezTriple) */ if (fcu->bezt && fcu->totvert) { - /* we either include all regardless of muting, or only non-muted */ - if ((filter & ANIMFILTER_KEYS_MUTED) || (fcu->flag & FCURVE_MUTED)==0) { - short replace = -1; - int i = binarysearch_bezt_index(fcu->bezt, frame, fcu->totvert, &replace); - - /* binarysearch_bezt_index will set replace to be 0 or 1 - * - obviously, 1 represents a match - */ - if (replace) { - /* sanity check: 'i' may in rare cases exceed arraylen */ - if ((i >= 0) && (i < fcu->totvert)) - return 1; - } - } + if (fcurve_frame_has_keyframe(fcu, frame, filter)) + return 1; } } diff --git a/source/blender/editors/include/ED_keyframing.h b/source/blender/editors/include/ED_keyframing.h index ffebb42ce99..503d71b0d3e 100644 --- a/source/blender/editors/include/ED_keyframing.h +++ b/source/blender/editors/include/ED_keyframing.h @@ -199,6 +199,11 @@ void ANIM_OT_remove_driver_button(struct wmOperatorType *ot); /* ************ Keyframe Checking ******************** */ +/* Lesser Keyframe Checking API call: + * - Used for the buttons to check for keyframes... + */ +short fcurve_frame_has_keyframe(struct FCurve *fcu, float frame, short filter); + /* Main Keyframe Checking API call: * Checks whether a keyframe exists for the given ID-block one the given frame. * - It is recommended to call this method over the other keyframe-checkers directly, diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c index 4a26db29160..be4087de525 100644 --- a/source/blender/editors/interface/interface_anim.c +++ b/source/blender/editors/interface/interface_anim.c @@ -18,6 +18,8 @@ #include "RNA_access.h" #include "RNA_types.h" +#include "ED_keyframing.h" + #include "UI_interface.h" #include "WM_api.h" @@ -47,7 +49,7 @@ void ui_but_anim_flag(uiBut *but, float cfra) if (fcu) { but->flag |= UI_BUT_ANIMATED; - if (on_keyframe_fcurve(fcu, cfra)) + if (fcurve_frame_has_keyframe(fcu, cfra, 0)) but->flag |= UI_BUT_ANIMATED_KEY; } } diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index 7b9f2faf08a..bbb666d01cc 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -291,6 +291,9 @@ static void nla_draw_strip (AnimData *adt, NlaTrack *nlt, NlaStrip *strip, View2 gl_round_box_shade(GL_POLYGON, strip->start, yminc, strip->end, ymaxc, 0.0, 0.5, 0.1); + /* draw influence 'curve' */ + // TODO: + /* draw strip outline * - color used here is to indicate active vs non-active */ @@ -378,11 +381,9 @@ static void nla_draw_strip_text (NlaTrack *nlt, NlaStrip *strip, int index, View case NLASTRIP_TYPE_CLIP: /* Action-Clip (default) */ default: - if (strip->act) - sprintf(str, "%d | Act: %s | %.2f %s %.2f", - index, strip->act->id.name+2, strip->start, dir, strip->end); - else - sprintf(str, "%d | Act: ", index); // xxx... need a better format? + sprintf(str, "%d | Act: %s | %.2f %s %.2f", + index, ((strip->act)?strip->act->id.name+2:""), + strip->start, dir, strip->end); break; } @@ -396,9 +397,9 @@ static void nla_draw_strip_text (NlaTrack *nlt, NlaStrip *strip, int index, View * - padding of 2 'units' on either side */ // TODO: make this centered? - rect.xmin= strip->start + 2; + rect.xmin= strip->start + 0.5f; rect.ymin= yminc; - rect.xmax= strip->end - 2; + rect.xmax= strip->end - 0.5f; rect.ymax= ymaxc; /* add this string to the cache of texts to draw*/ From 518911e78c2ae4511cbb9261c5cca410c0a77d73 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 9 Jul 2009 01:04:42 +0000 Subject: [PATCH 104/114] NLA SoC: Assorted cleanups * Some cleanups aimed at giving some (neglible) speedups * Preparation for NLA-Strip keyframes to be editable --- source/blender/blenkernel/BKE_nla.h | 2 + source/blender/blenkernel/intern/anim_sys.c | 8 ++-- source/blender/blenkernel/intern/nla.c | 41 ++++++++++++++++++- .../editors/interface/interface_anim.c | 10 +++-- source/blender/makesdna/DNA_anim_types.h | 2 + 5 files changed, 55 insertions(+), 8 deletions(-) diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index 7fdff7e41f7..04d4b0f8da2 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -83,6 +83,8 @@ struct NlaStrip *BKE_nlastrip_find_active(struct NlaTrack *nlt); short BKE_nlastrip_within_bounds(struct NlaStrip *strip, float min, float max); +short BKE_nlatrack_has_animated_strips(struct NlaTrack *nlt); +short BKE_nlatracks_have_animated_strips(ListBase *tracks); void BKE_nlastrip_validate_fcurves(struct NlaStrip *strip); /* ............ */ diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 1037b2fd15d..ebe3d28cb21 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -392,10 +392,10 @@ void BKE_keyingsets_free (ListBase *list) short animsys_remap_path (AnimMapper *remap, char *path, char **dst) { /* is there a valid remapping table to use? */ - if (remap) { + //if (remap) { /* find a matching entry... to use to remap */ // ...TODO... - } + //} /* nothing suitable found, so just set dst to look at path (i.e. no alloc/free needed) */ *dst= path; @@ -521,7 +521,6 @@ static void animsys_evaluate_drivers (PointerRNA *ptr, AnimData *adt, float ctim short ok= 0; /* check if this driver's curve should be skipped */ - // FIXME: maybe we shouldn't check for muted, though that would make things more confusing, as there's already too many ways to disable? if ((fcu->flag & (FCURVE_MUTED|FCURVE_DISABLED)) == 0) { /* check if driver itself is tagged for recalculation */ @@ -1185,6 +1184,9 @@ static void animsys_evaluate_nla (PointerRNA *ptr, AnimData *adt, float ctime) ListBase echannels= {NULL, NULL}; NlaEvalStrip *nes; + // TODO: need to zero out all channels used, otherwise we have problems with threadsafety + // and also when the user jumps between different times instead of moving sequentially... + /* 1. get the stack of strips to evaluate at current time (influence calculated here) */ for (nlt=adt->nla_tracks.first; nlt; nlt=nlt->next, track_index++) { /* if tweaking is on and this strip is the tweaking track, stop on this one */ diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 217444d16d2..c697f639021 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -926,7 +926,6 @@ void BKE_nlatrack_set_active (ListBase *tracks, NlaTrack *nlt_a) nlt_a->flag |= NLATRACK_ACTIVE; } - /* Check if there is any space in the given track to add a strip of the given length */ short BKE_nlatrack_has_space (NlaTrack *nlt, float start, float end) { @@ -1050,6 +1049,46 @@ short nlastrip_is_first (AnimData *adt, NlaStrip *strip) return 1; } +/* Animated Strips ------------------------------------------- */ + +/* Check if the given NLA-Track has any strips with own F-Curves */ +short BKE_nlatrack_has_animated_strips (NlaTrack *nlt) +{ + NlaStrip *strip; + + /* sanity checks */ + if ELEM(NULL, nlt, nlt->strips.first) + return 0; + + /* check each strip for F-Curves only (don't care about whether the flags are set) */ + for (strip= nlt->strips.first; strip; strip= strip->next) { + if (strip->fcurves.first) + return 1; + } + + /* none found */ + return 0; +} + +/* Check if given NLA-Tracks have any strips with own F-Curves */ +short BKE_nlatracks_have_animated_strips (ListBase *tracks) +{ + NlaTrack *nlt; + + /* sanity checks */ + if ELEM(NULL, tracks, tracks->first) + return 0; + + /* check each track, stopping on the first hit */ + for (nlt= tracks->first; nlt; nlt= nlt->next) { + if (BKE_nlatrack_has_animated_strips(nlt)) + return 1; + } + + /* none found */ + return 0; +} + /* Validate the NLA-Strips 'control' F-Curves based on the flags set*/ void BKE_nlastrip_validate_fcurves (NlaStrip *strip) { diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c index be4087de525..7c439f408ba 100644 --- a/source/blender/editors/interface/interface_anim.c +++ b/source/blender/editors/interface/interface_anim.c @@ -30,12 +30,15 @@ void ui_but_anim_flag(uiBut *but, float cfra) { but->flag &= ~(UI_BUT_ANIMATED|UI_BUT_ANIMATED_KEY|UI_BUT_DRIVEN); - - if(but->rnaprop && but->rnapoin.id.data) { + + /* there must be some RNA-pointer + property combo for this button */ + if (but->rnaprop && but->rnapoin.id.data && + RNA_property_animateable(&but->rnapoin, but->rnaprop)) + { AnimData *adt= BKE_animdata_from_id(but->rnapoin.id.data); FCurve *fcu; char *path; - + if (adt) { if ((adt->action && adt->action->curves.first) || (adt->drivers.first)) { /* XXX this function call can become a performance bottleneck */ @@ -113,7 +116,6 @@ void ui_but_anim_remove_driver(bContext *C) WM_operator_name_call(C, "ANIM_OT_remove_driver_button", WM_OP_INVOKE_DEFAULT, NULL); } -// TODO: refine the logic for adding/removing drivers... void ui_but_anim_menu(bContext *C, uiBut *but) { uiPopupMenu *pup; diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h index cb9dc8f0bc7..ac8d44a86e6 100644 --- a/source/blender/makesdna/DNA_anim_types.h +++ b/source/blender/makesdna/DNA_anim_types.h @@ -741,6 +741,8 @@ enum { ADT_NLA_EDIT_ON = (1<<2), /* active Action for 'tweaking' does not have mapping applied for editing */ ADT_NLA_EDIT_NOMAP = (1<<3), + /* NLA-Strip F-Curves are expanded in UI */ + ADT_NLA_SKEYS_COLLAPSED = (1<<4), /* drivers expanded in UI */ ADT_DRIVERS_COLLAPSED = (1<<10), From 27d80365fa3abf5db3ebf509d712d947564d8447 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 9 Jul 2009 01:32:13 +0000 Subject: [PATCH 105/114] NLA SoC: Toggle muting operator - HKEY This operator provides a quick way of toggling the muted-status of several strips at the same time. --- source/blender/editors/space_nla/nla_edit.c | 60 +++++++++++++++++++ source/blender/editors/space_nla/nla_header.c | 4 ++ source/blender/editors/space_nla/nla_intern.h | 2 + source/blender/editors/space_nla/nla_ops.c | 5 ++ 4 files changed, 71 insertions(+) diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index 0198a66949e..262255524db 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -857,6 +857,66 @@ void NLA_OT_split (wmOperatorType *ot) /* *********************************************** */ /* NLA Editing Operations (Modifying) */ +/* ******************** Toggle Muting Operator ************************** */ +/* Toggles whether strips are muted or not */ + +static int nlaedit_toggle_mute_exec (bContext *C, wmOperator *op) +{ + bAnimContext ac; + + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* get a list of the editable tracks being shown in the NLA */ + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* go over all selected strips */ + for (ale= anim_data.first; ale; ale= ale->next) { + NlaTrack *nlt= (NlaTrack *)ale->data; + NlaStrip *strip; + + /* for every selected strip, toggle muting */ + for (strip= nlt->strips.first; strip; strip= strip->next) { + if (strip->flag & NLASTRIP_FLAG_SELECT) { + /* just flip the mute flag for now */ + // TODO: have a pre-pass to check if mute all or unmute all? + strip->flag ^= NLASTRIP_FLAG_MUTED; + } + } + } + + /* free temp data */ + BLI_freelistN(&anim_data); + + /* set notifier that things have changed */ + ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); + WM_event_add_notifier(C, NC_SCENE, NULL); + + /* done */ + return OPERATOR_FINISHED; +} + +void NLA_OT_mute_toggle (wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Toggle Muting"; + ot->idname= "NLA_OT_mute_toggle"; + ot->description= "Mute or un-muted selected strips."; + + /* api callbacks */ + ot->exec= nlaedit_toggle_mute_exec; + ot->poll= nlaop_poll_tweakmode_off; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + /* ******************** Move Strips Up Operator ************************** */ /* Tries to move the selected strips into the track above if possible. */ diff --git a/source/blender/editors/space_nla/nla_header.c b/source/blender/editors/space_nla/nla_header.c index 9a2806ed9c1..a82056d6efb 100644 --- a/source/blender/editors/space_nla/nla_header.c +++ b/source/blender/editors/space_nla/nla_header.c @@ -168,6 +168,10 @@ static void nla_editmenu(bContext *C, uiLayout *layout, void *arg_unused) uiItemS(layout); + uiItemO(layout, NULL, 0, "NLA_OT_mute_toggle"); + + uiItemS(layout); + uiItemO(layout, NULL, 0, "NLA_OT_apply_scale"); uiItemO(layout, NULL, 0, "NLA_OT_clear_scale"); diff --git a/source/blender/editors/space_nla/nla_intern.h b/source/blender/editors/space_nla/nla_intern.h index 3d8bfcd0546..7cc09707ba7 100644 --- a/source/blender/editors/space_nla/nla_intern.h +++ b/source/blender/editors/space_nla/nla_intern.h @@ -98,6 +98,8 @@ void NLA_OT_duplicate(wmOperatorType *ot); void NLA_OT_delete(wmOperatorType *ot); void NLA_OT_split(wmOperatorType *ot); +void NLA_OT_mute_toggle(wmOperatorType *ot); + void NLA_OT_move_up(wmOperatorType *ot); void NLA_OT_move_down(wmOperatorType *ot); diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c index 25fd8db668c..431768c4e02 100644 --- a/source/blender/editors/space_nla/nla_ops.c +++ b/source/blender/editors/space_nla/nla_ops.c @@ -153,6 +153,8 @@ void nla_operatortypes(void) WM_operatortype_append(NLA_OT_delete); WM_operatortype_append(NLA_OT_split); + WM_operatortype_append(NLA_OT_mute_toggle); + WM_operatortype_append(NLA_OT_move_up); WM_operatortype_append(NLA_OT_move_down); @@ -256,6 +258,9 @@ static void nla_keymap_main (wmWindowManager *wm, ListBase *keymap) /* split */ WM_keymap_add_item(keymap, "NLA_OT_split", YKEY, KM_PRESS, 0, 0); + /* toggles */ + WM_keymap_add_item(keymap, "NLA_OT_mute_toggle", HKEY, KM_PRESS, 0, 0); + /* move up */ WM_keymap_add_item(keymap, "NLA_OT_move_up", PAGEUPKEY, KM_PRESS, 0, 0); /* move down */ From f9749ea2e778165cf6e92cc263f5be3a802247fa Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 9 Jul 2009 07:28:45 +0000 Subject: [PATCH 106/114] NLA SoC: Influence of strip now gets drawn as a greyish curve on the strip I'm not quite happy with how this works yet. It looks quite crude, and might be contributing to the clutter here. Ideas on this welcome. --- source/blender/editors/space_nla/nla_draw.c | 69 ++++++++++++++++++++- 1 file changed, 67 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index bbb666d01cc..7b2b19c19f6 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -58,6 +58,7 @@ #include "BLI_rand.h" #include "BKE_animsys.h" +#include "BKE_fcurve.h" #include "BKE_nla.h" #include "BKE_context.h" #include "BKE_screen.h" @@ -224,6 +225,70 @@ static void nla_strip_get_color_inside (AnimData *adt, NlaStrip *strip, float co } } +/* helper call for drawing influence/time control curves for a given NLA-strip */ +static void nla_draw_strip_curves (NlaStrip *strip, View2D *v2d, float yminc, float ymaxc) +{ + const float yheight = ymaxc - yminc; + + /* drawing color is simply a light-grey */ + // TODO: is this color suitable? + // XXX nasty hacked color for now... which looks quite bad too... + glColor3f(0.7f, 0.7f, 0.7f); + + /* draw with AA'd line, 2 units thick (it's either 1 or 2 px) */ + glEnable(GL_LINE_SMOOTH); + glEnable(GL_BLEND); + glLineWidth(2.0f); + + /* influence -------------------------- */ + if (strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) { + FCurve *fcu= list_find_fcurve(&strip->fcurves, "influence", 0); + float cfra; + + /* plot the curve (over the strip's main region) */ + glBegin(GL_LINE_STRIP); + /* sample at 1 frame intervals, and draw + * - min y-val is yminc, max is y-maxc, so clamp in those regions + */ + for (cfra= strip->start; cfra <= strip->end; cfra += 1.0f) { + float y= evaluate_fcurve(fcu, cfra); // assume this to be in 0-1 range + glVertex2f(cfra, ((y*yheight)+yminc)); + } + glEnd(); // GL_LINE_STRIP + } + else { + /* use blend in/out values only if both aren't zero */ + if ((IS_EQ(strip->blendin, 0.0f) && IS_EQ(strip->blendout, 0.0f))==0) { + glBegin(GL_LINE_STRIP); + /* start of strip - if no blendin, start straight at 1, otherwise from 0 to 1 over blendin frames */ + if (IS_EQ(strip->blendin, 0.0f) == 0) { + glVertex2f(strip->start, yminc); + glVertex2f(strip->start + strip->blendin, ymaxc); + } + else + glVertex2f(strip->start, ymaxc); + + /* end of strip */ + if (IS_EQ(strip->blendout, 0.0f) == 0) { + glVertex2f(strip->end - strip->blendout, ymaxc); + glVertex2f(strip->end, yminc); + } + else + glVertex2f(strip->end, ymaxc); + glEnd(); // GL_LINE_STRIP + } + } + + /* time -------------------------- */ + // XXX do we want to draw this curve? in a different colour too? + + /* turn off AA'd lines */ + glDisable(GL_LINE_SMOOTH); + glDisable(GL_BLEND); + glLineWidth(1.0f); +} + +/* main call for drawing a single NLA-strip */ static void nla_draw_strip (AnimData *adt, NlaTrack *nlt, NlaStrip *strip, View2D *v2d, float yminc, float ymaxc) { float color[3]; @@ -291,8 +356,8 @@ static void nla_draw_strip (AnimData *adt, NlaTrack *nlt, NlaStrip *strip, View2 gl_round_box_shade(GL_POLYGON, strip->start, yminc, strip->end, ymaxc, 0.0, 0.5, 0.1); - /* draw influence 'curve' */ - // TODO: + /* draw strip's control 'curves' */ + nla_draw_strip_curves(strip, v2d, yminc, ymaxc); /* draw strip outline * - color used here is to indicate active vs non-active From c1f3b86f861028c9f1b6e8eedc5d4c07b77205a7 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 9 Jul 2009 13:14:51 +0000 Subject: [PATCH 107/114] NLA SoC: Cleanup of Keyframe Drawing code for DopeSheet * Removed the glaMapping stuff in favour of remapping the keyframes manually. The old code was causing some mess, and not really working well for the DopeSheet with various mappings being used. * Fixed NLA-mapped selection in DopeSheet. Clicking on individual keyframes should now work ok. More testing required though. * Keyframes in DopeSheet are now drawn fully using OpenGL (instead of icons). They look less tactile now, but this may be compensated with in terms of speed? Previously I disabled this type of drawing due to issues with some cards. Enabled again for now, but mainly because I couldn't get the icons to line up nicely in screenspace... * Borderselect in DopeSheet. I've had a look at issues with it selecting the wrong channel's keyframes. The issues don't seem to be solved yet though... will look again tomorrow. --- .../editors/animation/keyframes_draw.c | 288 ++++++++---------- source/blender/editors/armature/poselib.c | 2 +- .../editors/include/ED_keyframes_draw.h | 38 +-- .../editors/space_action/action_draw.c | 96 ++---- .../editors/space_action/action_select.c | 66 ++-- source/blender/editors/space_nla/nla_draw.c | 2 +- .../editors/space_view3d/drawarmature.c | 9 +- 7 files changed, 197 insertions(+), 304 deletions(-) diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c index 56b1c63db74..f122e045776 100644 --- a/source/blender/editors/animation/keyframes_draw.c +++ b/source/blender/editors/animation/keyframes_draw.c @@ -51,7 +51,6 @@ #include "DNA_armature_types.h" #include "DNA_camera_types.h" #include "DNA_curve_types.h" -#include "DNA_ipo_types.h" #include "DNA_object_types.h" #include "DNA_screen_types.h" #include "DNA_scene_types.h" @@ -64,6 +63,7 @@ #include "DNA_gpencil_types.h" #include "DNA_windowmanager_types.h" #include "DNA_world_types.h" +#include "DNA_view2d_types.h" #include "BKE_action.h" #include "BKE_depsgraph.h" @@ -234,45 +234,82 @@ static ActKeyColumn *cfra_find_actkeycolumn (ListBase *keys, float cframe) return NULL; } -#if 0 // disabled, as some intel cards have problems with this -/* Draw a simple diamond shape with a filled in center (in screen space) */ -static void draw_key_but(int x, int y, short w, short h, int sel) +/* coordinates for diamond shape */ +static const float _unit_diamond_shape[4][2] = { + {0.0f, 1.0f}, /* top vert */ + {1.0f, 0.0f}, /* mid-right */ + {0.0f, -1.0f}, /* bottom vert */ + {-1.0f, 0.0f} /* mid-left */ +}; + +/* draw a simple diamond shape with OpenGL */ +static void draw_keyframe_shape (float x, float y, float xscale, float hsize, short sel) { - int xmin= x, ymin= y; - int xmax= x+w-1, ymax= y+h-1; - int xc= (xmin+xmax)/2, yc= (ymin+ymax)/2; + static GLuint displist1=0; + static GLuint displist2=0; + + /* initialise 2 display lists for diamond shape - one empty, one filled */ + if (displist1 == 0) { + displist1= glGenLists(1); + glNewList(displist1, GL_COMPILE); + + glBegin(GL_LINE_LOOP); + glVertex2fv(_unit_diamond_shape[0]); + glVertex2fv(_unit_diamond_shape[1]); + glVertex2fv(_unit_diamond_shape[2]); + glVertex2fv(_unit_diamond_shape[3]); + glEnd(); + glEndList(); + } + if (displist2 == 0) { + displist2= glGenLists(1); + glNewList(displist2, GL_COMPILE); + + glBegin(GL_QUADS); + glVertex2fv(_unit_diamond_shape[0]); + glVertex2fv(_unit_diamond_shape[1]); + glVertex2fv(_unit_diamond_shape[2]); + glVertex2fv(_unit_diamond_shape[3]); + glEnd(); + glEndList(); + } + + /* adjust view transform before starting */ + glTranslatef(x, y, 0.0f); + glScalef(1.0f/xscale*hsize, hsize, 1.0f); + + /* anti-aliased lines for more consistent appearance */ + glEnable(GL_LINE_SMOOTH); + + /* draw! ---------------------------- */ /* interior - hardcoded colors (for selected and unselected only) */ - if (sel) glColor3ub(0xF1, 0xCA, 0x13); + if (sel) UI_ThemeColorShade(TH_STRIP_SELECT, 50);//glColor3ub(0xF1, 0xCA, 0x13); else glColor3ub(0xE9, 0xE9, 0xE9); + glCallList(displist2); - glBegin(GL_QUADS); - glVertex2i(xc, ymin); - glVertex2i(xmax, yc); - glVertex2i(xc, ymax); - glVertex2i(xmin, yc); - glEnd(); - - - /* outline */ + /* exterior - black frame */ glColor3ub(0, 0, 0); + glCallList(displist1); - glBegin(GL_LINE_LOOP); - glVertex2i(xc, ymin); - glVertex2i(xmax, yc); - glVertex2i(xc, ymax); - glVertex2i(xmin, yc); - glEnd(); + glDisable(GL_LINE_SMOOTH); + + /* restore view transform */ + glScalef(xscale/hsize, 1.0f/hsize, 1.0); + glTranslatef(-x, -y, 0.0f); } -#endif -static void draw_keylist(gla2DDrawInfo *di, ListBase *keys, ListBase *blocks, float ypos) +static void draw_keylist(View2D *v2d, ListBase *keys, ListBase *blocks, float ypos) { ActKeyColumn *ak; ActKeyBlock *ab; + float xscale; glEnable(GL_BLEND); + /* get View2D scaling factor */ + UI_view2d_getscale(v2d, &xscale, NULL); + /* draw keyblocks */ if (blocks) { for (ab= blocks->first; ab; ab= ab->next) { @@ -292,18 +329,13 @@ static void draw_keylist(gla2DDrawInfo *di, ListBase *keys, ListBase *blocks, fl totCurves = (startCurves>endCurves)? endCurves: startCurves; if (ab->totcurve >= totCurves) { - int sc_xa, sc_xb, sc_ya, sc_yb; - - /* get co-ordinates of block */ - gla2DDrawTranslatePt(di, ab->start, ypos, &sc_xa, &sc_ya); - gla2DDrawTranslatePt(di, ab->end, ypos, &sc_xb, &sc_yb); - /* draw block */ if (ab->sel) UI_ThemeColor4(TH_STRIP_SELECT); else UI_ThemeColor4(TH_STRIP); - glRectf((float)sc_xa, (float)sc_ya-3, (float)sc_xb, (float)sc_yb+5); + + glRectf(ab->start, ypos-5, ab->end, ypos+5); } } } @@ -311,18 +343,28 @@ static void draw_keylist(gla2DDrawInfo *di, ListBase *keys, ListBase *blocks, fl /* draw keys */ if (keys) { for (ak= keys->first; ak; ak= ak->next) { - int sc_x, sc_y; + /* draw using OpenGL - uglier but faster */ + // NOTE: a previous version of this didn't work nice for some intel cards + draw_keyframe_shape(ak->cfra, ypos, xscale, 5.0f, (ak->sel & SELECT)); + +#if 0 // OLD CODE + //int sc_x, sc_y; /* get co-ordinate to draw at */ - gla2DDrawTranslatePt(di, ak->cfra, ypos, &sc_x, &sc_y); + //gla2DDrawTranslatePt(di, ak->cfra, ypos, &sc_x, &sc_y); /* draw using icons - old way which is slower but more proven */ - if (ak->sel & SELECT) UI_icon_draw_aspect((float)sc_x-7, (float)sc_y-6, ICON_SPACE2, 1.0f); - else UI_icon_draw_aspect((float)sc_x-7, (float)sc_y-6, ICON_SPACE3, 1.0f); + //if (ak->sel & SELECT) UI_icon_draw_aspect((float)sc_x-7, (float)sc_y-6, ICON_SPACE2, 1.0f); + //else UI_icon_draw_aspect((float)sc_x-7, (float)sc_y-6, ICON_SPACE3, 1.0f); +#endif // OLD CODE +#if 0 // NEW NON-WORKING CODE + /* draw icon */ + // FIXME: this draws slightly wrong, as we need to apply some offset for icon, but that depends on scaling + // so for now disabled + //int icon = (ak->sel & SELECT) ? ICON_SPACE2 : ICON_SPACE3; + //UI_icon_draw_aspect(ak->cfra, ypos-6, icon, 1.0f); +#endif // NEW NON-WORKING CODE - /* draw using OpenGL - slightly uglier but faster */ - // NOTE: disabled for now, as some intel cards seem to have problems with this - //draw_key_but(sc_x-5, sc_y-4, 11, 11, (ak->sel & SELECT)); } } @@ -331,81 +373,80 @@ static void draw_keylist(gla2DDrawInfo *di, ListBase *keys, ListBase *blocks, fl /* *************************** Channel Drawing Funcs *************************** */ -void draw_scene_channel(gla2DDrawInfo *di, ActKeysInc *aki, Scene *sce, float ypos) +void draw_scene_channel(View2D *v2d, bDopeSheet *ads, Scene *sce, float ypos) { ListBase keys = {0, 0}; ListBase blocks = {0, 0}; - scene_to_keylist(sce, &keys, &blocks, aki); - draw_keylist(di, &keys, &blocks, ypos); + scene_to_keylist(ads, sce, &keys, &blocks); + draw_keylist(v2d, &keys, &blocks, ypos); BLI_freelistN(&keys); BLI_freelistN(&blocks); } -void draw_object_channel(gla2DDrawInfo *di, ActKeysInc *aki, Object *ob, float ypos) +void draw_object_channel(View2D *v2d, bDopeSheet *ads, Object *ob, float ypos) { ListBase keys = {0, 0}; ListBase blocks = {0, 0}; - ob_to_keylist(ob, &keys, &blocks, aki); - draw_keylist(di, &keys, &blocks, ypos); + ob_to_keylist(ads, ob, &keys, &blocks); + draw_keylist(v2d, &keys, &blocks, ypos); BLI_freelistN(&keys); BLI_freelistN(&blocks); } -void draw_fcurve_channel(gla2DDrawInfo *di, ActKeysInc *aki, FCurve *fcu, float ypos) +void draw_fcurve_channel(View2D *v2d, AnimData *adt, FCurve *fcu, float ypos) { ListBase keys = {0, 0}; ListBase blocks = {0, 0}; - fcurve_to_keylist(fcu, &keys, &blocks, aki); - draw_keylist(di, &keys, &blocks, ypos); + fcurve_to_keylist(adt, fcu, &keys, &blocks); + draw_keylist(v2d, &keys, &blocks, ypos); BLI_freelistN(&keys); BLI_freelistN(&blocks); } -void draw_agroup_channel(gla2DDrawInfo *di, ActKeysInc *aki, bActionGroup *agrp, float ypos) +void draw_agroup_channel(View2D *v2d, AnimData *adt, bActionGroup *agrp, float ypos) { ListBase keys = {0, 0}; ListBase blocks = {0, 0}; - agroup_to_keylist(agrp, &keys, &blocks, aki); - draw_keylist(di, &keys, &blocks, ypos); + agroup_to_keylist(adt, agrp, &keys, &blocks); + draw_keylist(v2d, &keys, &blocks, ypos); BLI_freelistN(&keys); BLI_freelistN(&blocks); } -void draw_action_channel(gla2DDrawInfo *di, ActKeysInc *aki, bAction *act, float ypos) +void draw_action_channel(View2D *v2d, AnimData *adt, bAction *act, float ypos) { ListBase keys = {0, 0}; ListBase blocks = {0, 0}; - action_to_keylist(act, &keys, &blocks, aki); - draw_keylist(di, &keys, &blocks, ypos); + action_to_keylist(adt, act, &keys, &blocks); + draw_keylist(v2d, &keys, &blocks, ypos); BLI_freelistN(&keys); BLI_freelistN(&blocks); } -void draw_gpl_channel(gla2DDrawInfo *di, ActKeysInc *aki, bGPDlayer *gpl, float ypos) +void draw_gpl_channel(View2D *v2d, bDopeSheet *ads, bGPDlayer *gpl, float ypos) { ListBase keys = {0, 0}; - gpl_to_keylist(gpl, &keys, NULL, aki); - draw_keylist(di, &keys, NULL, ypos); + gpl_to_keylist(ads, gpl, &keys, NULL); + draw_keylist(v2d, &keys, NULL, ypos); BLI_freelistN(&keys); } /* *************************** Keyframe List Conversions *************************** */ -void scene_to_keylist(Scene *sce, ListBase *keys, ListBase *blocks, ActKeysInc *aki) +void scene_to_keylist(bDopeSheet *ads, Scene *sce, ListBase *keys, ListBase *blocks) { if (sce) { - bDopeSheet *ads= (aki)? (aki->ads) : NULL; AnimData *adt; int filterflag; @@ -421,7 +462,7 @@ void scene_to_keylist(Scene *sce, ListBase *keys, ListBase *blocks, ActKeysInc * // TODO: when we adapt NLA system, this needs to be the NLA-scaled version if (adt->action) - action_to_keylist(adt->action, keys, blocks, aki); + action_to_keylist(adt, adt->action, keys, blocks); } /* world animdata */ @@ -430,17 +471,16 @@ void scene_to_keylist(Scene *sce, ListBase *keys, ListBase *blocks, ActKeysInc * // TODO: when we adapt NLA system, this needs to be the NLA-scaled version if (adt->action) - action_to_keylist(adt->action, keys, blocks, aki); + action_to_keylist(adt, adt->action, keys, blocks); } } } -void ob_to_keylist(Object *ob, ListBase *keys, ListBase *blocks, ActKeysInc *aki) +void ob_to_keylist(bDopeSheet *ads, Object *ob, ListBase *keys, ListBase *blocks) { Key *key= ob_get_key(ob); if (ob) { - bDopeSheet *ads= (aki)? (aki->ads) : NULL; int filterflag; /* get filterflag */ @@ -451,79 +491,18 @@ void ob_to_keylist(Object *ob, ListBase *keys, ListBase *blocks, ActKeysInc *aki /* Add action keyframes */ if (ob->adt && ob->adt->action) - action_nlascaled_to_keylist(ob->adt, ob->adt->action, keys, blocks, aki); + action_to_keylist(ob->adt, ob->adt->action, keys, blocks); /* Add shapekey keyframes (only if dopesheet allows, if it is available) */ - // TODO: when we adapt NLA system, this needs to be the NLA-scaled version if ((key && key->adt && key->adt->action) && !(filterflag & ADS_FILTER_NOSHAPEKEYS)) - action_to_keylist(key->adt->action, keys, blocks, aki); + action_to_keylist(key->adt, key->adt->action, keys, blocks); -#if 0 // XXX old animation system - /* Add material keyframes (only if dopesheet allows, if it is available) */ - if ((ob->totcol) && !(filterflag & ADS_FILTER_NOMAT)) { - short a; - - for (a=0; atotcol; a++) { - Material *ma= give_current_material(ob, a); - - if (ELEM(NULL, ma, ma->ipo) == 0) - ipo_to_keylist(ma->ipo, keys, blocks, aki); - } - } - - /* Add object data keyframes */ - switch (ob->type) { - case OB_CAMERA: /* ------- Camera ------------ */ - { - Camera *ca= (Camera *)ob->data; - if ((ca->ipo) && !(filterflag & ADS_FILTER_NOCAM)) - ipo_to_keylist(ca->ipo, keys, blocks, aki); - } - break; - case OB_LAMP: /* ---------- Lamp ----------- */ - { - Lamp *la= (Lamp *)ob->data; - if ((la->ipo) && !(filterflag & ADS_FILTER_NOLAM)) - ipo_to_keylist(la->ipo, keys, blocks, aki); - } - break; - case OB_CURVE: /* ------- Curve ---------- */ - { - Curve *cu= (Curve *)ob->data; - if ((cu->ipo) && !(filterflag & ADS_FILTER_NOCUR)) - ipo_to_keylist(cu->ipo, keys, blocks, aki); - } - break; - } -#endif // XXX old animation system + // TODO: restore materials, and object data, etc. } } -static short bezt_in_aki_range (ActKeysInc *aki, BezTriple *bezt) -{ - /* when aki == NULL, we don't care about range */ - if (aki == NULL) - return 1; - - /* if start and end are both 0, then don't care about range */ - if (IS_EQ(aki->start, 0) && IS_EQ(aki->end, 0)) - return 1; - - /* if nla-scaling is in effect, apply appropriate scaling adjustments */ -#if 0 // XXX this was from some buggy code... do not port for now - if (aki->ob) { - float frame= get_action_frame_inv(aki->ob, bezt->vec[1][0]); - return IN_RANGE(frame, aki->start, aki->end); - } - else { - /* check if in range */ - return IN_RANGE(bezt->vec[1][0], aki->start, aki->end); - } -#endif // XXX this was from some buggy code... do not port for now - return 1; -} -void fcurve_to_keylist(FCurve *fcu, ListBase *keys, ListBase *blocks, ActKeysInc *aki) +void fcurve_to_keylist(AnimData *adt, FCurve *fcu, ListBase *keys, ListBase *blocks) { BezTriple *bezt; ActKeyColumn *ak, *ak2; @@ -531,15 +510,17 @@ void fcurve_to_keylist(FCurve *fcu, ListBase *keys, ListBase *blocks, ActKeysInc int v; if (fcu && fcu->totvert && fcu->bezt) { + /* apply NLA-mapping (if applicable) */ + if (adt) + ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 1); + /* loop through beztriples, making ActKeys and ActKeyBlocks */ bezt= fcu->bezt; for (v=0; v < fcu->totvert; v++, bezt++) { /* only if keyframe is in range (optimisation) */ - if (bezt_in_aki_range(aki, bezt)) { - add_bezt_to_keycolumnslist(keys, bezt); - if (blocks) add_bezt_to_keyblockslist(blocks, fcu, v); - } + add_bezt_to_keycolumnslist(keys, bezt); + if (blocks) add_bezt_to_keyblockslist(blocks, fcu, v); } /* update the number of curves that elements have appeared in */ @@ -575,65 +556,38 @@ void fcurve_to_keylist(FCurve *fcu, ListBase *keys, ListBase *blocks, ActKeysInc } } } + + /* unapply NLA-mapping if applicable */ + ANIM_nla_mapping_apply_fcurve(adt, fcu, 1, 1); } } -void agroup_to_keylist(bActionGroup *agrp, ListBase *keys, ListBase *blocks, ActKeysInc *aki) +void agroup_to_keylist(AnimData *adt, bActionGroup *agrp, ListBase *keys, ListBase *blocks) { FCurve *fcu; if (agrp) { /* loop through F-Curves */ for (fcu= agrp->channels.first; fcu && fcu->grp==agrp; fcu= fcu->next) { - fcurve_to_keylist(fcu, keys, blocks, aki); + fcurve_to_keylist(adt, fcu, keys, blocks); } } } -void action_to_keylist(bAction *act, ListBase *keys, ListBase *blocks, ActKeysInc *aki) +void action_to_keylist(AnimData *adt, bAction *act, ListBase *keys, ListBase *blocks) { FCurve *fcu; if (act) { /* loop through F-Curves */ for (fcu= act->curves.first; fcu; fcu= fcu->next) { - fcurve_to_keylist(fcu, keys, blocks, aki); + fcurve_to_keylist(adt, fcu, keys, blocks); } } } -void action_nlascaled_to_keylist(AnimData *adt, bAction *act, ListBase *keys, ListBase *blocks, ActKeysInc *aki) -{ - FCurve *fcu; - AnimData *oldadt= NULL; - - /* although apply and clearing NLA-mapping pre-post creating keylist does impact on performance, - * the effects should be fairly minimal, as we're already going through the keyframes multiple times - * already for blocks too... - */ - if (act) { - /* if 'aki' is provided, store it's current ob to restore later as it might not be the same */ - if (aki) { - oldadt= aki->adt; - aki->adt= adt; - } - - /* loop through F-Curves - * - scaling correction only does times for center-points, so should be faster - */ - for (fcu= act->curves.first; fcu; fcu= fcu->next) { - ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 1); - fcurve_to_keylist(fcu, keys, blocks, aki); - ANIM_nla_mapping_apply_fcurve(adt, fcu, 1, 1); - } - - /* if 'aki' is provided, restore ob */ - if (aki) - aki->adt= oldadt; - } -} -void gpl_to_keylist(bGPDlayer *gpl, ListBase *keys, ListBase *blocks, ActKeysInc *aki) +void gpl_to_keylist(bDopeSheet *ads, bGPDlayer *gpl, ListBase *keys, ListBase *blocks) { bGPDframe *gpf; ActKeyColumn *ak; diff --git a/source/blender/editors/armature/poselib.c b/source/blender/editors/armature/poselib.c index 8cbfebebff6..fcc1e8f9644 100644 --- a/source/blender/editors/armature/poselib.c +++ b/source/blender/editors/armature/poselib.c @@ -227,7 +227,7 @@ void poselib_validate_act (bAction *act) } /* determine which frames have keys */ - action_to_keylist(act, &keys, NULL, NULL); + action_to_keylist(NULL, act, &keys, NULL); /* for each key, make sure there is a correspnding pose */ for (ak= keys.first; ak; ak= ak->next) { diff --git a/source/blender/editors/include/ED_keyframes_draw.h b/source/blender/editors/include/ED_keyframes_draw.h index d2269300d24..22ee7a42121 100644 --- a/source/blender/editors/include/ED_keyframes_draw.h +++ b/source/blender/editors/include/ED_keyframes_draw.h @@ -33,13 +33,14 @@ struct AnimData; struct BezTriple; struct FCurve; -struct gla2DDrawInfo; +struct bDopeSheet; struct bAction; struct bActionGroup; struct Object; struct ListBase; struct bGPDlayer; struct Scene; +struct View2D; /* ****************************** Base Structs ****************************** */ @@ -66,34 +67,23 @@ typedef struct ActKeyBlock { short totcurve; } ActKeyBlock; - -/* Inclusion-Range Limiting Struct (optional) */ -typedef struct ActKeysInc { - struct bDopeSheet *ads; /* dopesheet data (for dopesheet mode) */ - struct AnimData *adt; /* owner for NLA-mapping info */ - short actmode; /* mode of the Action Editor (-1 is for NLA) */ - - float start, end; /* frames (global-time) to only consider keys between */ // XXX not used anymore! -} ActKeysInc; - /* ******************************* Methods ****************************** */ /* Channel Drawing */ -void draw_fcurve_channel(struct gla2DDrawInfo *di, ActKeysInc *aki, struct FCurve *fcu, float ypos); -void draw_agroup_channel(struct gla2DDrawInfo *di, ActKeysInc *aki, struct bActionGroup *agrp, float ypos); -void draw_action_channel(struct gla2DDrawInfo *di, ActKeysInc *aki, struct bAction *act, float ypos); -void draw_object_channel(struct gla2DDrawInfo *di, ActKeysInc *aki, struct Object *ob, float ypos); -void draw_scene_channel(struct gla2DDrawInfo *di, ActKeysInc *aki, struct Scene *sce, float ypos); -void draw_gpl_channel(struct gla2DDrawInfo *di, ActKeysInc *aki, struct bGPDlayer *gpl, float ypos); +void draw_fcurve_channel(struct View2D *v2d, struct AnimData *adt, struct FCurve *fcu, float ypos); +void draw_agroup_channel(struct View2D *v2d, struct AnimData *adt, struct bActionGroup *agrp, float ypos); +void draw_action_channel(struct View2D *v2d, struct AnimData *adt, struct bAction *act, float ypos); +void draw_object_channel(struct View2D *v2d, struct bDopeSheet *ads, struct Object *ob, float ypos); +void draw_scene_channel(struct View2D *v2d, struct bDopeSheet *ads, struct Scene *sce, float ypos); +void draw_gpl_channel(struct View2D *v2d, struct bDopeSheet *ads, struct bGPDlayer *gpl, float ypos); /* Keydata Generation */ -void fcurve_to_keylist(struct FCurve *fcu, ListBase *keys, ListBase *blocks, ActKeysInc *aki); -void agroup_to_keylist(struct bActionGroup *agrp, ListBase *keys, ListBase *blocks, ActKeysInc *aki); -void action_to_keylist(struct bAction *act, ListBase *keys, ListBase *blocks, ActKeysInc *aki); -void action_nlascaled_to_keylist(struct AnimData *adt, struct bAction *act, ListBase *keys, ListBase *blocks, ActKeysInc *aki); -void ob_to_keylist(struct Object *ob, ListBase *keys, ListBase *blocks, ActKeysInc *aki); -void scene_to_keylist(struct Scene *sce, ListBase *keys, ListBase *blocks, ActKeysInc *aki); -void gpl_to_keylist(struct bGPDlayer *gpl, ListBase *keys, ListBase *blocks, ActKeysInc *aki); +void fcurve_to_keylist(struct AnimData *adt, struct FCurve *fcu, ListBase *keys, ListBase *blocks); +void agroup_to_keylist(struct AnimData *adt, struct bActionGroup *agrp, ListBase *keys, ListBase *blocks); +void action_to_keylist(struct AnimData *adt, struct bAction *act, ListBase *keys, ListBase *blocks); +void ob_to_keylist(struct bDopeSheet *ads, struct Object *ob, ListBase *keys, ListBase *blocks); +void scene_to_keylist(struct bDopeSheet *ads, struct Scene *sce, ListBase *keys, ListBase *blocks); +void gpl_to_keylist(struct bDopeSheet *ads, struct bGPDlayer *gpl, ListBase *keys, ListBase *blocks); #endif /* ED_KEYFRAMES_DRAW_H */ diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c index 910b9733bc8..743cc1f128e 100644 --- a/source/blender/editors/space_action/action_draw.c +++ b/source/blender/editors/space_action/action_draw.c @@ -960,27 +960,8 @@ void draw_channel_names(bAnimContext *ac, SpaceAction *saction, ARegion *ar) /* ************************************************************************* */ /* Keyframes */ -ActKeysInc *init_aki_data(bAnimContext *ac, bAnimListElem *ale) -{ - static ActKeysInc aki; - - /* no need to set settings if wrong context */ - if ((ac->data == NULL) || ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET)==0) - return NULL; - - /* if strip is mapped, store settings */ - aki.adt= ANIM_nla_mapping_get(ac, ale); - - if (ac->datatype == ANIMCONT_DOPESHEET) - aki.ads= (bDopeSheet *)ac->data; - else - aki.ads= NULL; - aki.actmode= ac->datatype; - - /* always return pointer... */ - return &aki; -} - +/* extra padding for lengths (to go under scrollers) */ +#define EXTRA_SCROLL_PAD 100.0f /* draw keyframes in each channel */ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar) @@ -990,13 +971,11 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar) int filter; View2D *v2d= &ar->v2d; + bDopeSheet *ads= &saction->ads; AnimData *adt= NULL; - gla2DDrawInfo *di; - rcti scr_rct; - int act_start, act_end, dummy; + float act_start, act_end, y; int height, items; - float y, sta, end; char col1[3], col2[3]; char col1a[3], col2a[3]; @@ -1006,6 +985,7 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar) /* get theme colors */ UI_GetThemeColor3ubv(TH_BACK, col2); UI_GetThemeColor3ubv(TH_HILITE, col1); + UI_GetThemeColor3ubv(TH_GROUP, col2a); UI_GetThemeColor3ubv(TH_GROUP_ACTIVE, col1a); @@ -1013,26 +993,14 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar) UI_GetThemeColor3ubv(TH_DOPESHEET_CHANNELSUBOB, col2b); /* set view-mapping rect (only used for x-axis), for NLA-scaling mapping with less calculation */ - scr_rct.xmin= ar->winrct.xmin + ar->v2d.mask.xmin; - scr_rct.ymin= ar->winrct.ymin + ar->v2d.mask.ymin; - scr_rct.xmax= ar->winrct.xmin + ar->v2d.hor.xmax; - scr_rct.ymax= ar->winrct.ymin + ar->v2d.mask.ymax; - di= glaBegin2DDraw(&scr_rct, &v2d->cur); /* if in NLA there's a strip active, map the view */ if (ac->datatype == ANIMCONT_ACTION) { adt= ANIM_nla_mapping_get(ac, NULL); - if (adt) - ANIM_nla_mapping_draw(di, adt, 0); - /* start and end of action itself */ - calc_action_range(ac->data, &sta, &end, 0); - gla2DDrawTranslatePt(di, sta, 0.0f, &act_start, &dummy); - gla2DDrawTranslatePt(di, end, 0.0f, &act_end, &dummy); - - if (adt) - ANIM_nla_mapping_draw(di, adt, 1); + // TODO: this has not had scaling applied + calc_action_range(ac->data, &act_start, &act_end, 0); } /* build list of channels to draw */ @@ -1063,7 +1031,7 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar) if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) { - int frame1_x, channel_y, sel=0; + int sel=0; /* determine if any need to draw channel */ if (ale->datatype != ALE_NONE) { @@ -1102,8 +1070,6 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar) } if (ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET)) { - gla2DDrawTranslatePt(di, v2d->cur.xmin, y, &frame1_x, &channel_y); - switch (ale->type) { case ANIMTYPE_SCENE: case ANIMTYPE_OBJECT: @@ -1139,36 +1105,32 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar) } /* draw region twice: firstly backdrop, then the current range */ - glRectf((float)frame1_x, (float)channel_y-ACHANNEL_HEIGHT_HALF, (float)v2d->hor.xmax, (float)channel_y+ACHANNEL_HEIGHT_HALF); + glRectf(v2d->cur.xmin, (float)y-ACHANNEL_HEIGHT_HALF, v2d->cur.xmax+EXTRA_SCROLL_PAD, (float)y+ACHANNEL_HEIGHT_HALF); if (ac->datatype == ANIMCONT_ACTION) - glRectf((float)act_start, (float)channel_y-ACHANNEL_HEIGHT_HALF, (float)act_end, (float)channel_y+ACHANNEL_HEIGHT_HALF); + glRectf(act_start, (float)y-ACHANNEL_HEIGHT_HALF, act_end, (float)y+ACHANNEL_HEIGHT_HALF); } else if (ac->datatype == ANIMCONT_SHAPEKEY) { - gla2DDrawTranslatePt(di, 1, y, &frame1_x, &channel_y); - /* all frames that have a frame number less than one * get a desaturated orange background */ glColor4ub(col2[0], col2[1], col2[2], 0x22); - glRectf(0.0f, (float)channel_y-ACHANNEL_HEIGHT_HALF, (float)frame1_x, (float)channel_y+ACHANNEL_HEIGHT_HALF); + glRectf(0.0f, (float)y-ACHANNEL_HEIGHT_HALF, 1.0f, (float)y+ACHANNEL_HEIGHT_HALF); /* frames one and higher get a saturated orange background */ glColor4ub(col2[0], col2[1], col2[2], 0x44); - glRectf((float)frame1_x, (float)channel_y-ACHANNEL_HEIGHT_HALF, (float)v2d->hor.xmax, (float)channel_y+ACHANNEL_HEIGHT_HALF); + glRectf(1.0f, (float)y-ACHANNEL_HEIGHT_HALF, v2d->cur.xmax+EXTRA_SCROLL_PAD, (float)y+ACHANNEL_HEIGHT_HALF); } else if (ac->datatype == ANIMCONT_GPENCIL) { - gla2DDrawTranslatePt(di, v2d->cur.xmin, y, &frame1_x, &channel_y); - /* frames less than one get less saturated background */ if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22); else glColor4ub(col2[0], col2[1], col2[2], 0x22); - glRectf(0.0f, (float)channel_y-ACHANNEL_HEIGHT_HALF, (float)frame1_x, (float)channel_y+ACHANNEL_HEIGHT_HALF); + glRectf(0.0f, (float)y-ACHANNEL_HEIGHT_HALF, v2d->cur.xmin, (float)y+ACHANNEL_HEIGHT_HALF); /* frames one and higher get a saturated background */ if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x44); else glColor4ub(col2[0], col2[1], col2[2], 0x44); - glRectf((float)frame1_x, (float)channel_y-ACHANNEL_HEIGHT_HALF, (float)v2d->hor.xmax, (float)channel_y+ACHANNEL_HEIGHT_HALF); + glRectf(v2d->cur.xmin, (float)y-ACHANNEL_HEIGHT_HALF, v2d->cur.xmax+EXTRA_SCROLL_PAD, (float)y+ACHANNEL_HEIGHT_HALF); } } } @@ -1195,36 +1157,29 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar) { /* check if anything to show for this channel */ if (ale->datatype != ALE_NONE) { - ActKeysInc *aki= init_aki_data(ac, ale); adt= ANIM_nla_mapping_get(ac, ale); - if (adt) - ANIM_nla_mapping_draw(di, adt, 0); - /* draw 'keyframes' for each specific datatype */ switch (ale->datatype) { case ALE_SCE: - draw_scene_channel(di, aki, ale->key_data, y); + draw_scene_channel(v2d, ads, ale->key_data, y); break; case ALE_OB: - draw_object_channel(di, aki, ale->key_data, y); + draw_object_channel(v2d, ads, ale->key_data, y); break; case ALE_ACT: - draw_action_channel(di, aki, ale->key_data, y); + draw_action_channel(v2d, adt, ale->key_data, y); break; case ALE_GROUP: - draw_agroup_channel(di, aki, ale->data, y); + draw_agroup_channel(v2d, adt, ale->data, y); break; case ALE_FCURVE: - draw_fcurve_channel(di, aki, ale->key_data, y); + draw_fcurve_channel(v2d, adt, ale->key_data, y); break; case ALE_GPFRAME: - draw_gpl_channel(di, aki, ale->data, y); + draw_gpl_channel(v2d, ads, ale->data, y); break; } - - if (adt) - ANIM_nla_mapping_draw(di, adt, 1); } } @@ -1236,16 +1191,11 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar) /* black line marking 'current frame' for Time-Slide transform mode */ if (saction->flag & SACTION_MOVING) { - int frame1_x; - - gla2DDrawTranslatePt(di, saction->timeslide, 0, &frame1_x, &dummy); - cpack(0x0); + glColor3f(0.0f, 0.0f, 0.0f); glBegin(GL_LINES); - glVertex2f((float)frame1_x, (float)v2d->mask.ymin - 100); - glVertex2f((float)frame1_x, (float)v2d->mask.ymax); + glVertex2f(saction->timeslide, v2d->cur.ymin-EXTRA_SCROLL_PAD) + glVertex2f(saction->timeslide, v2d->cur.ymax); glEnd(); } - - glaEnd2DDraw(di); } diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c index 5b87c04b311..8f95f5ea52d 100644 --- a/source/blender/editors/space_action/action_select.c +++ b/source/blender/editors/space_action/action_select.c @@ -223,7 +223,8 @@ static void borderselect_action (bAnimContext *ac, rcti rect, short mode, short BeztEditFunc ok_cb, select_cb; View2D *v2d= &ac->ar->v2d; rctf rectf; - float ymin=0, ymax=(float)(-ACHANNEL_HEIGHT); + //float ymin=0, ymax=(float)(-ACHANNEL_HEIGHT); + float ymin=0, ymax=(float)(-ACHANNEL_HEIGHT_HALF); /* convert mouse coordinates to frame ranges and channel coordinates corrected for view pan/zoom */ UI_view2d_region_to_view(v2d, rect.xmin, rect.ymin+2, &rectf.xmin, &rectf.ymin); @@ -743,12 +744,16 @@ static void mouse_action_keys (bAnimContext *ac, int mval[2], short select_mode, int filter; View2D *v2d= &ac->ar->v2d; + bDopeSheet *ads = NULL; int channel_index; short found = 0; float selx = 0.0f; float x, y; rctf rectf; + /* get dopesheet info */ + if (ac->datatype == ANIMCONT_DOPESHEET) + ads= ac->data; /* use View2D to determine the index of the channel (i.e a row in the list) where keyframe was */ UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y); @@ -773,46 +778,35 @@ static void mouse_action_keys (bAnimContext *ac, int mval[2], short select_mode, else { /* found match - must return here... */ AnimData *adt= ANIM_nla_mapping_get(ac, ale); - ActKeysInc *aki= init_aki_data(ac, ale); ActKeyColumn *ak; - float xmin, xmax; - - /* apply NLA-scaling correction? */ - if (adt) { - xmin= BKE_nla_tweakedit_remap(adt, rectf.xmin, NLATIME_CONVERT_UNMAP); - xmax= BKE_nla_tweakedit_remap(adt, rectf.xmax, NLATIME_CONVERT_UNMAP); - } - else { - xmin= rectf.xmin; - xmax= rectf.xmax; - } /* make list of keyframes */ + // TODO: it would be great if we didn't have to apply this to all the keyframes to do this... if (ale->key_data) { switch (ale->datatype) { case ALE_OB: { Object *ob= (Object *)ale->key_data; - ob_to_keylist(ob, &anim_keys, NULL, aki); + ob_to_keylist(ads, ob, &anim_keys, NULL); } break; case ALE_ACT: { bAction *act= (bAction *)ale->key_data; - action_to_keylist(act, &anim_keys, NULL, aki); + action_to_keylist(adt, act, &anim_keys, NULL); } break; case ALE_FCURVE: { FCurve *fcu= (FCurve *)ale->key_data; - fcurve_to_keylist(fcu, &anim_keys, NULL, aki); + fcurve_to_keylist(adt, fcu, &anim_keys, NULL); } break; } } else if (ale->type == ANIMTYPE_GROUP) { bActionGroup *agrp= (bActionGroup *)ale->data; - agroup_to_keylist(agrp, &anim_keys, NULL, aki); + agroup_to_keylist(adt, agrp, &anim_keys, NULL); } else if (ale->type == ANIMTYPE_GPDATABLOCK) { /* cleanup */ @@ -822,13 +816,17 @@ static void mouse_action_keys (bAnimContext *ac, int mval[2], short select_mode, } else if (ale->type == ANIMTYPE_GPLAYER) { bGPDlayer *gpl= (bGPDlayer *)ale->data; - gpl_to_keylist(gpl, &anim_keys, NULL, aki); + gpl_to_keylist(ads, gpl, &anim_keys, NULL); } /* loop through keyframes, finding one that was clicked on */ for (ak= anim_keys.first; ak; ak= ak->next) { - if (IN_RANGE(ak->cfra, xmin, xmax)) { - selx= ak->cfra; + if (IN_RANGE(ak->cfra, rectf.xmin, rectf.xmax)) { + /* set the frame to use, and apply inverse-correction for NLA-mapping + * so that the frame will get selected by the selection functiosn without + * requiring to map each frame once again... + */ + selx= BKE_nla_tweakedit_remap(adt, ak->cfra, NLATIME_CONVERT_UNMAP); found= 1; break; } @@ -884,19 +882,21 @@ static void mouse_action_keys (bAnimContext *ac, int mval[2], short select_mode, } /* only select keyframes if we clicked on a valid channel and hit something */ - if (ale && found) { - /* apply selection to keyframes */ - if (/*gpl*/0) { - /* grease pencil */ - //select_gpencil_frame(gpl, (int)selx, selectmode); - } - else if (column) { - /* select all keyframes in the same frame as the one we hit on the active channel */ - actkeys_mselect_column(ac, select_mode, selx); - } - else { - /* select the nominated keyframe on the given frame */ - actkeys_mselect_single(ac, ale, select_mode, selx); + if (ale) { + if (found) { + /* apply selection to keyframes */ + if (/*gpl*/0) { + /* grease pencil */ + //select_gpencil_frame(gpl, (int)selx, selectmode); + } + else if (column) { + /* select all keyframes in the same frame as the one we hit on the active channel */ + actkeys_mselect_column(ac, select_mode, selx); + } + else { + /* select the nominated keyframe on the given frame */ + actkeys_mselect_single(ac, ale, select_mode, selx); + } } /* free this channel */ diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index 7b2b19c19f6..3385906979a 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -143,7 +143,7 @@ static void nla_action_draw_keyframes (AnimData *adt, View2D *v2d, float y) glColor3f(0.0f, 0.0f, 0.0f); /* get a list of the keyframes with NLA-scaling applied */ - action_nlascaled_to_keylist(adt, adt->action, &keys, NULL, NULL); + action_to_keylist(adt, adt->action, &keys, NULL); /* get View2D scaling factor */ UI_view2d_getscale(v2d, &xscale, NULL); diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c index 0827bcaa9ae..c0f71ae6124 100644 --- a/source/blender/editors/space_view3d/drawarmature.c +++ b/source/blender/editors/space_view3d/drawarmature.c @@ -2173,7 +2173,7 @@ static void draw_pose_paths(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec if (adt) { bActionGroup *agrp= action_groups_find_named(adt->action, pchan->name); if (agrp) - agroup_to_keylist(agrp, &keys, NULL, NULL); + agroup_to_keylist(adt, agrp, &keys, NULL); } /* Draw slightly-larger yellow dots at each keyframe */ @@ -2320,18 +2320,17 @@ static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, RegionView3D *rv3d, bArmature *arm= ob->data; bPose *posen, *poseo; ListBase keys= {NULL, NULL}; - ActKeysInc aki = {0, 0, 0}; ActKeyColumn *ak, *akn; float start, end, range, colfac, i; int cfrao, flago; - aki.start= start = (float)arm->ghostsf; - aki.end= end = (float)arm->ghostef; + start = (float)arm->ghostsf; + end = (float)arm->ghostef; if (end <= start) return; /* get keyframes - then clip to only within range */ - action_to_keylist(act, &keys, NULL, &aki); + action_to_keylist(adt, act, &keys, NULL); range= 0; for (ak= keys.first; ak; ak= akn) { akn= ak->next; From d7a7081e633f458d3c68f6ccff5376c0340fe42e Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 10 Jul 2009 00:32:13 +0000 Subject: [PATCH 108/114] NLA SoC: Tweaks from feedback from Broken + jez * Renamed the 'blend' blending mode to 'replace', since that's what it usually does * Drawing a darkened rect behind the keyframes shown in the action line -- * Fixed typo made last night which broke compiling * Consolidated all the keyframe-shape drawing code to use a single codebase. Even if we don't ultimately go with OpenGL keyframes, there's always a tidy option for that now. --- source/blender/blenkernel/intern/anim_sys.c | 2 +- source/blender/blenkernel/intern/ipo.c | 2 +- .../editors/animation/keyframes_draw.c | 27 ++-- .../editors/include/ED_keyframes_draw.h | 16 +++ .../editors/space_action/action_draw.c | 2 +- source/blender/editors/space_nla/nla_draw.c | 128 +++++++++--------- source/blender/makesdna/DNA_anim_types.h | 2 +- source/blender/makesrna/intern/rna_nla.c | 2 +- 8 files changed, 102 insertions(+), 79 deletions(-) diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index ebe3d28cb21..19337f9de5d 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -859,7 +859,7 @@ static void nlaevalchan_accumulate (NlaEvalChannel *nec, NlaEvalStrip *nes, shor nec->value *= value; break; - case NLASTRIP_MODE_BLEND: + case NLASTRIP_MODE_REPLACE: default: // TODO: do we really want to blend by default? it seems more uses might prefer add... /* do linear interpolation * - the influence of the accumulated data (elsewhere, that is called dstweight) diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index c3c5483574e..cf7e486613b 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -1518,7 +1518,7 @@ static void nlastrips_to_animdata (ID *id, ListBase *strips) /* blending */ strip->blendin= as->blendin; strip->blendout= as->blendout; - strip->blendmode= (as->mode==ACTSTRIPMODE_ADD) ? NLASTRIP_MODE_ADD : NLASTRIP_MODE_BLEND; + strip->blendmode= (as->mode==ACTSTRIPMODE_ADD) ? NLASTRIP_MODE_ADD : NLASTRIP_MODE_REPLACE; if (as->flag & ACTSTRIP_AUTO_BLENDS) strip->flag |= NLASTRIP_FLAG_AUTO_BLENDS; /* assorted setting flags */ diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c index f122e045776..1db78beb2cb 100644 --- a/source/blender/editors/animation/keyframes_draw.c +++ b/source/blender/editors/animation/keyframes_draw.c @@ -243,7 +243,7 @@ static const float _unit_diamond_shape[4][2] = { }; /* draw a simple diamond shape with OpenGL */ -static void draw_keyframe_shape (float x, float y, float xscale, float hsize, short sel) +void draw_keyframe_shape (float x, float y, float xscale, float hsize, short sel, short mode) { static GLuint displist1=0; static GLuint displist2=0; @@ -281,16 +281,21 @@ static void draw_keyframe_shape (float x, float y, float xscale, float hsize, sh /* anti-aliased lines for more consistent appearance */ glEnable(GL_LINE_SMOOTH); - /* draw! ---------------------------- */ + /* draw! */ + if ELEM(mode, KEYFRAME_SHAPE_INSIDE, KEYFRAME_SHAPE_BOTH) { + /* interior - hardcoded colors (for selected and unselected only) */ + if (sel) UI_ThemeColorShade(TH_STRIP_SELECT, 50); + else glColor3ub(0xE9, 0xE9, 0xE9); + + glCallList(displist2); + } - /* interior - hardcoded colors (for selected and unselected only) */ - if (sel) UI_ThemeColorShade(TH_STRIP_SELECT, 50);//glColor3ub(0xF1, 0xCA, 0x13); - else glColor3ub(0xE9, 0xE9, 0xE9); - glCallList(displist2); - - /* exterior - black frame */ - glColor3ub(0, 0, 0); - glCallList(displist1); + if ELEM(mode, KEYFRAME_SHAPE_FRAME, KEYFRAME_SHAPE_BOTH) { + /* exterior - black frame */ + glColor3ub(0, 0, 0); + + glCallList(displist1); + } glDisable(GL_LINE_SMOOTH); @@ -345,7 +350,7 @@ static void draw_keylist(View2D *v2d, ListBase *keys, ListBase *blocks, float yp for (ak= keys->first; ak; ak= ak->next) { /* draw using OpenGL - uglier but faster */ // NOTE: a previous version of this didn't work nice for some intel cards - draw_keyframe_shape(ak->cfra, ypos, xscale, 5.0f, (ak->sel & SELECT)); + draw_keyframe_shape(ak->cfra, ypos, xscale, 5.0f, (ak->sel & SELECT), KEYFRAME_SHAPE_BOTH); #if 0 // OLD CODE //int sc_x, sc_y; diff --git a/source/blender/editors/include/ED_keyframes_draw.h b/source/blender/editors/include/ED_keyframes_draw.h index 22ee7a42121..63adcf39c12 100644 --- a/source/blender/editors/include/ED_keyframes_draw.h +++ b/source/blender/editors/include/ED_keyframes_draw.h @@ -67,6 +67,22 @@ typedef struct ActKeyBlock { short totcurve; } ActKeyBlock; + +/* *********************** Keyframe Drawing ****************************** */ + +/* options for keyframe shape drawing */ +typedef enum eKeyframeShapeDrawOpts { + /* only the border */ + KEYFRAME_SHAPE_FRAME = 0, + /* only the inside filling */ + KEYFRAME_SHAPE_INSIDE, + /* the whole thing */ + KEYFRAME_SHAPE_BOTH +} eKeyframeShapeDrawOpts; + +/* draw simple diamond-shape keyframe (with OpenGL) */ +void draw_keyframe_shape (float x, float y, float xscale, float hsize, short sel, short mode); + /* ******************************* Methods ****************************** */ /* Channel Drawing */ diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c index 743cc1f128e..93d061e8bf3 100644 --- a/source/blender/editors/space_action/action_draw.c +++ b/source/blender/editors/space_action/action_draw.c @@ -1194,7 +1194,7 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar) glColor3f(0.0f, 0.0f, 0.0f); glBegin(GL_LINES); - glVertex2f(saction->timeslide, v2d->cur.ymin-EXTRA_SCROLL_PAD) + glVertex2f(saction->timeslide, v2d->cur.ymin-EXTRA_SCROLL_PAD); glVertex2f(saction->timeslide, v2d->cur.ymax); glEnd(); } diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index 3385906979a..6219acf6fae 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -91,66 +91,78 @@ extern void gl_round_box_shade(int mode, float minx, float miny, float maxx, flo /* *********************************************** */ /* Strips */ -/* Keyframe Ghosts ---------------------- */ +/* Action-Line ---------------------- */ -/* helper func - draw keyframe as a frame only */ -static void draw_nla_keyframe_ghost (float x, float y, float xscale, float hsize) +/* get colors for drawing Action-Line + * NOTE: color returned includes fine-tuned alpha! + */ +static void nla_action_get_color (AnimData *adt, bAction *act, float color[4]) { - static GLuint displist=0; - - /* initialise empty diamond shape */ - if (displist == 0) { - const float dist= 1.0f; - - displist= glGenLists(1); - glNewList(displist, GL_COMPILE); - - glBegin(GL_LINE_LOOP); - glVertex2f(0.0f, dist); - glVertex2f(dist, 0.0f); - glVertex2f(0.0f, -dist); - glVertex2f(-dist, 0.0f); - glEnd(); - - glEndList(); + // TODO: if tweaking some action, use the same color as for the tweaked track (quick hack done for now) + if (adt && (adt->flag & ADT_NLA_EDIT_ON)) { + // greenish color (same as tweaking strip) - hardcoded for now + color[0]= 0.30f; + color[1]= 0.95f; + color[2]= 0.10f; + color[3]= 0.30f; + } + else { + if (act) { + // reddish color - hardcoded for now + color[0]= 0.8f; + color[1]= 0.2f; + color[2]= 0.0f; + color[3]= 0.4f; + } + else { + // greyish-red color - hardcoded for now + color[0]= 0.6f; + color[1]= 0.5f; + color[2]= 0.5f; + color[3]= 0.3f; + } } - - /* adjust view transform before starting */ - glTranslatef(x, y, 0.0f); - glScalef(1.0f/xscale*hsize, hsize, 1.0f); - - /* anti-aliased lines for more consistent appearance */ - glEnable(GL_LINE_SMOOTH); - - /* draw! */ - glCallList(displist); - - glDisable(GL_LINE_SMOOTH); - - /* restore view transform */ - glScalef(xscale/hsize, 1.0f/hsize, 1.0); - glTranslatef(-x, -y, 0.0f); } /* draw the keyframes in the specified Action */ -static void nla_action_draw_keyframes (AnimData *adt, View2D *v2d, float y) +static void nla_action_draw_keyframes (AnimData *adt, bAction *act, View2D *v2d, float y, float ymin, float ymax) { ListBase keys = {NULL, NULL}; ActKeyColumn *ak; - float xscale; - - /* for now, color is hardcoded to be black */ - glColor3f(0.0f, 0.0f, 0.0f); + float xscale, f1, f2; + float color[4]; /* get a list of the keyframes with NLA-scaling applied */ - action_to_keylist(adt, adt->action, &keys, NULL); + action_to_keylist(adt, act, &keys, NULL); + + if ELEM(NULL, act, keys.first) + return; + + /* draw a darkened region behind the strips + * - get and reset the background color, this time without the alpha to stand out better + */ + nla_action_get_color(adt, act, color); + glColor3fv(color); + /* - draw a rect from the first to the last frame (no extra overlaps for now) + * that is slightly stumpier than the track background (hardcoded 2-units here) + */ + f1= ((ActKeyColumn *)keys.first)->cfra; + f2= ((ActKeyColumn *)keys.last)->cfra; + + glRectf(f1, ymin+2, f2, ymax-2); + /* get View2D scaling factor */ UI_view2d_getscale(v2d, &xscale, NULL); - /* just draw each keyframe as a simple dot (regardless of the selection status) */ + /* for now, color is hardcoded to be black */ + glColor3f(0.0f, 0.0f, 0.0f); + + /* just draw each keyframe as a simple dot (regardless of the selection status) + * - size is 3.0f which is smaller than the editable keyframes, so that there is a distinction + */ for (ak= keys.first; ak; ak= ak->next) - draw_nla_keyframe_ghost(ak->cfra, y, xscale, 3.0f); + draw_keyframe_shape(ak->cfra, y, xscale, 3.0f, 0, KEYFRAME_SHAPE_FRAME); /* free icons */ BLI_freelistN(&keys); @@ -158,6 +170,7 @@ static void nla_action_draw_keyframes (AnimData *adt, View2D *v2d, float y) /* Strips (Proper) ---------------------- */ +/* get colors for drawing NLA-Strips */ static void nla_strip_get_color_inside (AnimData *adt, NlaStrip *strip, float color[3]) { if (strip->type == NLASTRIP_TYPE_TRANSITION) { @@ -179,6 +192,7 @@ static void nla_strip_get_color_inside (AnimData *adt, NlaStrip *strip, float co } else if (strip->type == NLASTRIP_TYPE_META) { /* Meta Clip */ + // TODO: should temporary metas get different colours too? if (strip->flag & NLASTRIP_FLAG_SELECT) { /* selected - use a bold purple color */ // FIXME: hardcoded temp-hack colors @@ -535,6 +549,7 @@ void draw_nla_main_data (bAnimContext *ac, SpaceNla *snla, ARegion *ar) case ANIMTYPE_NLAACTION: { AnimData *adt= BKE_animdata_from_id(ale->id); + float color[4]; /* just draw a semi-shaded rect spanning the width of the viewable area if there's data, * and a second darker rect within which we draw keyframe indicator dots if there's data @@ -542,30 +557,17 @@ void draw_nla_main_data (bAnimContext *ac, SpaceNla *snla, ARegion *ar) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); - // TODO: if tweaking some action, use the same color as for the tweaked track (quick hack done for now) - if (adt && (adt->flag & ADT_NLA_EDIT_ON)) { - // greenish color (same as tweaking strip) - hardcoded for now - glColor4f(0.3f, 0.95f, 0.1f, 0.3f); - } - else { - if (ale->data) - glColor4f(0.8f, 0.2f, 0.0f, 0.4f); // reddish color - hardcoded for now - else - glColor4f(0.6f, 0.5f, 0.5f, 0.3f); // greyish-red color - hardcoded for now - } - + /* get colors for drawing */ + nla_action_get_color(adt, ale->data, color); + glColor4fv(color); + /* draw slightly shifted up for greater separation from standard channels, * but also slightly shorter for some more contrast when viewing the strips */ - glBegin(GL_QUADS); - glVertex2f(v2d->cur.xmin, yminc+NLACHANNEL_SKIP); - glVertex2f(v2d->cur.xmin, ymaxc-NLACHANNEL_SKIP); - glVertex2f(v2d->cur.xmax, ymaxc-NLACHANNEL_SKIP); - glVertex2f(v2d->cur.xmax, yminc+NLACHANNEL_SKIP); - glEnd(); + glRectf(v2d->cur.xmin, yminc+NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc-NLACHANNEL_SKIP); /* draw keyframes in the action */ - nla_action_draw_keyframes(adt, v2d, y); + nla_action_draw_keyframes(adt, ale->data, v2d, y, yminc+NLACHANNEL_SKIP, ymaxc-NLACHANNEL_SKIP); /* draw 'embossed' lines above and below the strip for effect */ /* white base-lines */ diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h index ac8d44a86e6..d71beb8785b 100644 --- a/source/blender/makesdna/DNA_anim_types.h +++ b/source/blender/makesdna/DNA_anim_types.h @@ -464,7 +464,7 @@ typedef struct NlaStrip { /* NLA Strip Blending Mode */ enum { - NLASTRIP_MODE_BLEND = 0, + NLASTRIP_MODE_REPLACE = 0, NLASTRIP_MODE_ADD, NLASTRIP_MODE_SUBTRACT, NLASTRIP_MODE_MULTIPLY, diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c index 219feaad09b..97f35af1db7 100644 --- a/source/blender/makesrna/intern/rna_nla.c +++ b/source/blender/makesrna/intern/rna_nla.c @@ -239,7 +239,7 @@ void rna_def_nlastrip(BlenderRNA *brna) {NLASTRIP_TYPE_META, "META", 0, "Meta", "NLA Strip acts as a container for adjacent strips."}, {0, NULL, 0, NULL, NULL}}; static EnumPropertyItem prop_mode_blend_items[] = { - {NLASTRIP_MODE_BLEND, "BLEND", 0, "Blend", "Results of strip and accumulated results are combined in ratio governed by influence."}, + {NLASTRIP_MODE_REPLACE, "REPLACE", 0, "Replace", "Result strip replaces the accumulated results by amount specified by influence."}, {NLASTRIP_MODE_ADD, "ADD", 0, "Add", "Weighted result of strip is added to the accumlated results."}, {NLASTRIP_MODE_SUBTRACT, "SUBTRACT", 0, "Subtract", "Weighted result of strip is removed from the accumlated results."}, {NLASTRIP_MODE_MULTIPLY, "MULITPLY", 0, "Multiply", "Weighted result of strip is multiplied with the accumlated results."}, From b1a9281ed801ae8b2483cd4246880b1009efe955 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 10 Jul 2009 02:04:50 +0000 Subject: [PATCH 109/114] NLA SoC: Fixes for renamed headers (BIF_transform.h -> ED_transform.h) --- source/blender/editors/space_action/action_header.c | 2 +- source/blender/editors/space_graph/graph_header.c | 2 +- source/blender/editors/space_nla/nla_edit.c | 3 +-- source/blender/editors/space_nla/nla_header.c | 5 ++--- source/blender/editors/space_nla/nla_ops.c | 3 +-- 5 files changed, 6 insertions(+), 9 deletions(-) diff --git a/source/blender/editors/space_action/action_header.c b/source/blender/editors/space_action/action_header.c index f4bb5b335a4..f5c85d4d983 100644 --- a/source/blender/editors/space_action/action_header.c +++ b/source/blender/editors/space_action/action_header.c @@ -48,6 +48,7 @@ #include "ED_anim_api.h" #include "ED_screen.h" +#include "ED_transform.h" #include "ED_types.h" #include "ED_util.h" @@ -58,7 +59,6 @@ #include "BIF_gl.h" #include "BIF_glutil.h" -#include "BIF_transform.h" #include "UI_interface.h" #include "UI_resources.h" diff --git a/source/blender/editors/space_graph/graph_header.c b/source/blender/editors/space_graph/graph_header.c index 6c12b44f082..05d9b2f7e6c 100644 --- a/source/blender/editors/space_graph/graph_header.c +++ b/source/blender/editors/space_graph/graph_header.c @@ -43,6 +43,7 @@ #include "BKE_screen.h" #include "ED_anim_api.h" +#include "ED_transform.h" #include "ED_screen.h" #include "ED_types.h" #include "ED_util.h" @@ -54,7 +55,6 @@ #include "BIF_gl.h" #include "BIF_glutil.h" -#include "BIF_transform.h" #include "UI_interface.h" #include "UI_resources.h" diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index 262255524db..6cbc9cab253 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -61,8 +61,7 @@ #include "ED_markers.h" #include "ED_space_api.h" #include "ED_screen.h" - -#include "BIF_transform.h" +#include "ED_transform.h" #include "RNA_access.h" #include "RNA_define.h" diff --git a/source/blender/editors/space_nla/nla_header.c b/source/blender/editors/space_nla/nla_header.c index a82056d6efb..8e4c71b9f80 100644 --- a/source/blender/editors/space_nla/nla_header.c +++ b/source/blender/editors/space_nla/nla_header.c @@ -53,11 +53,12 @@ #include "ED_util.h" #include "ED_anim_api.h" +#include "ED_markers.h" #include "ED_space_api.h" #include "ED_screen.h" +#include "ED_transform.h" #include "BIF_gl.h" -#include "BIF_transform.h" #include "RNA_access.h" @@ -68,8 +69,6 @@ #include "UI_resources.h" #include "UI_view2d.h" -#include "ED_markers.h" - #include "nla_intern.h" /* button events */ diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c index 431768c4e02..ad5f5174690 100644 --- a/source/blender/editors/space_nla/nla_ops.c +++ b/source/blender/editors/space_nla/nla_ops.c @@ -53,8 +53,7 @@ #include "ED_anim_api.h" #include "ED_space_api.h" #include "ED_screen.h" - -#include "BIF_transform.h" +#include "ED_transform.h" #include "WM_api.h" #include "WM_types.h" From 6f0de59c551235d5e26281eca6e172d08ff5eb73 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 10 Jul 2009 10:48:25 +0000 Subject: [PATCH 110/114] NLA SoC: Notifier Fixes for Animation Editors I've gone through all the Animation Editor operators, making sure they send appropriate notifiers, and that these notifiers are handled. * Added a separate category for animation-related notifiers, since the old-style ones attached to specific datatypes only was turning out to be not too feasible. * For now, the focus has been on making sure that all Animation Editors update when there have been any potentially suitable changes at all. Later on, we can filter these more carefully to only take the ones we really need (for optimisation purposes) --- .../blender/editors/animation/anim_channels.c | 77 ++++++++++++++----- source/blender/editors/animation/anim_deps.c | 70 +---------------- .../editors/animation/keyframes_general.c | 2 + source/blender/editors/animation/keyingsets.c | 6 ++ source/blender/editors/include/ED_anim_api.h | 13 ---- .../editors/space_action/action_edit.c | 49 ++++++------ .../editors/space_action/action_select.c | 15 ++-- .../editors/space_action/space_action.c | 9 +++ .../blender/editors/space_graph/graph_edit.c | 62 +++++++-------- .../editors/space_graph/graph_select.c | 13 ++-- .../blender/editors/space_graph/space_graph.c | 6 ++ .../blender/editors/space_nla/nla_channels.c | 53 ++++++++++--- source/blender/editors/space_nla/nla_edit.c | 49 ++++-------- source/blender/editors/space_nla/nla_select.c | 7 +- source/blender/editors/space_nla/space_nla.c | 15 +++- .../editors/space_view3d/space_view3d.c | 9 +++ source/blender/editors/transform/transform.c | 22 ++---- source/blender/windowmanager/WM_types.h | 11 +++ 18 files changed, 260 insertions(+), 228 deletions(-) diff --git a/source/blender/editors/animation/anim_channels.c b/source/blender/editors/animation/anim_channels.c index 5e9abd42aeb..1cf553f6f26 100644 --- a/source/blender/editors/animation/anim_channels.c +++ b/source/blender/editors/animation/anim_channels.c @@ -614,8 +614,8 @@ static int animchannels_rearrange_exec(bContext *C, wmOperator *op) mode= RNA_enum_get(op->ptr, "direction"); rearrange_action_channels(&ac, mode); - /* set notifier tha things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_CHANNELS); + /* send notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_EDIT, NULL); return OPERATOR_FINISHED; } @@ -728,8 +728,8 @@ static int animchannels_visibility_toggle_exec(bContext *C, wmOperator *op) /* cleanup */ BLI_freelistN(&anim_data); - /* set notifier tha things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_CHANNELS); + /* send notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_EDIT, NULL); return OPERATOR_FINISHED; } @@ -992,8 +992,8 @@ static int animchannels_setflag_exec(bContext *C, wmOperator *op) /* modify setting */ setflag_anim_channels(&ac, setting, mode, 1); - /* set notifier tha things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_CHANNELS); + /* send notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_EDIT, NULL); return OPERATOR_FINISHED; } @@ -1101,8 +1101,8 @@ static int animchannels_expand_exec (bContext *C, wmOperator *op) /* modify setting */ setflag_anim_channels(&ac, ACHANNEL_SETTING_EXPAND, ACHANNEL_SETFLAG_ADD, onlysel); - /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_CHANNELS); + /* send notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_EDIT, NULL); return OPERATOR_FINISHED; } @@ -1142,8 +1142,8 @@ static int animchannels_collapse_exec (bContext *C, wmOperator *op) /* modify setting */ setflag_anim_channels(&ac, ACHANNEL_SETTING_EXPAND, ACHANNEL_SETFLAG_CLEAR, onlysel); - /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_CHANNELS); + /* send notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_EDIT, NULL); return OPERATOR_FINISHED; } @@ -1181,8 +1181,8 @@ static int animchannels_deselectall_exec(bContext *C, wmOperator *op) else ANIM_deselect_anim_channels(ac.data, ac.datatype, 1, ACHANNEL_SETFLAG_ADD); - /* set notifier tha things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_CHANNELS); + /* send notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_SELECT, NULL); return OPERATOR_FINISHED; } @@ -1310,6 +1310,9 @@ static int animchannels_borderselect_exec(bContext *C, wmOperator *op) /* apply borderselect animation channels */ borderselect_anim_channels(&ac, &rect, selectmode); + /* send notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_SELECT, NULL); + return OPERATOR_FINISHED; } @@ -1344,11 +1347,12 @@ void ANIM_OT_channels_select_border(wmOperatorType *ot) * NOTE: eventually, this should probably be phased out when many of these things are replaced with buttons */ -static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, short selectmode) +static int mouse_anim_channels (bAnimContext *ac, float x, int channel_index, short selectmode) { ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; int filter; + int notifierFlags = 0; /* get the channel that was clicked on */ /* filter channels */ @@ -1362,7 +1366,7 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s printf("Error: animation channel (index = %d) not found in mouse_anim_channels() \n", channel_index); BLI_freelistN(&anim_data); - return; + return 0; } /* selectmode -1 is a special case for ActionGroups only, which selects all of the channels underneath it only... */ @@ -1370,7 +1374,7 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s if ((selectmode == -1) && (ale->type != ANIMTYPE_GROUP)) { /* normal channels should not behave normally in this case */ BLI_freelistN(&anim_data); - return; + return 0; } /* action to take depends on what channel we've got */ @@ -1382,6 +1386,8 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s if (x < 16) { /* toggle expand */ sce->flag ^= SCE_DS_COLLAPSED; + + notifierFlags |= ND_ANIMCHAN_EDIT; } else { /* set selection status */ @@ -1392,6 +1398,8 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s else { sce->flag |= SCE_DS_SELECTED; } + + notifierFlags |= ND_ANIMCHAN_SELECT; } } break; @@ -1405,6 +1413,8 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s if (x < 16) { /* toggle expand */ ob->nlaflag ^= OB_ADS_COLLAPSED; // XXX + + notifierFlags |= ND_ANIMCHAN_EDIT; } else { /* set selection status */ @@ -1429,6 +1439,8 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s /* xxx should be ED_base_object_activate(), but we need context pointer for that... */ //set_active_base(base); + + notifierFlags |= ND_ANIMCHAN_SELECT; } } break; @@ -1436,18 +1448,21 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s { bAction *act= (bAction *)ale->data; act->flag ^= ACT_COLLAPSED; + notifierFlags |= ND_ANIMCHAN_EDIT; } break; case ANIMTYPE_FILLDRIVERS: { AnimData *adt= (AnimData* )ale->data; adt->flag ^= ADT_DRIVERS_COLLAPSED; + notifierFlags |= ND_ANIMCHAN_EDIT; } break; case ANIMTYPE_FILLMATD: { Object *ob= (Object *)ale->data; ob->nlaflag ^= OB_ADS_SHOWMATS; // XXX + notifierFlags |= ND_ANIMCHAN_EDIT; } break; @@ -1455,36 +1470,42 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s { Material *ma= (Material *)ale->data; ma->flag ^= MA_DS_EXPAND; + notifierFlags |= ND_ANIMCHAN_EDIT; } break; case ANIMTYPE_DSLAM: { Lamp *la= (Lamp *)ale->data; la->flag ^= LA_DS_EXPAND; + notifierFlags |= ND_ANIMCHAN_EDIT; } break; case ANIMTYPE_DSCAM: { Camera *ca= (Camera *)ale->data; ca->flag ^= CAM_DS_EXPAND; + notifierFlags |= ND_ANIMCHAN_EDIT; } break; case ANIMTYPE_DSCUR: { Curve *cu= (Curve *)ale->data; cu->flag ^= CU_DS_EXPAND; + notifierFlags |= ND_ANIMCHAN_EDIT; } break; case ANIMTYPE_DSSKEY: { Key *key= (Key *)ale->data; key->flag ^= KEYBLOCK_DS_EXPAND; + notifierFlags |= ND_ANIMCHAN_EDIT; } break; case ANIMTYPE_DSWOR: { World *wo= (World *)ale->data; wo->flag ^= WO_DS_EXPAND; + notifierFlags |= ND_ANIMCHAN_EDIT; } break; @@ -1496,18 +1517,22 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s if ((x < (offset+17)) && (agrp->channels.first)) { /* toggle expand */ agrp->flag ^= AGRP_EXPANDED; + notifierFlags |= ND_ANIMCHAN_EDIT; } else if ((x < (offset+32)) && (ac->spacetype==SPACE_IPO)) { /* toggle visibility (of grouped F-Curves in Graph editor) */ agrp->flag ^= AGRP_NOTVISIBLE; + notifierFlags |= ND_ANIMCHAN_EDIT; } else if (x >= (ACHANNEL_NAMEWIDTH-ACHANNEL_BUTTON_WIDTH)) { /* toggle protection/locking */ agrp->flag ^= AGRP_PROTECTED; + notifierFlags |= ND_ANIMCHAN_EDIT; } else if (x >= (ACHANNEL_NAMEWIDTH-2*ACHANNEL_BUTTON_WIDTH)) { /* toggle mute */ agrp->flag ^= AGRP_MUTED; + notifierFlags |= ND_ANIMCHAN_EDIT; } else { /* select/deselect group */ @@ -1536,6 +1561,8 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s /* if group is selected now, make group the 'active' one in the visible list */ if (agrp->flag & AGRP_SELECTED) ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, agrp, ANIMTYPE_GROUP); + + notifierFlags |= ND_ANIMCHAN_SELECT; } } break; @@ -1556,16 +1583,20 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s if (x >= (ACHANNEL_NAMEWIDTH-ACHANNEL_BUTTON_WIDTH)) { /* toggle protection (only if there's a toggle there) */ - if (fcu->bezt) + if (fcu->bezt) { fcu->flag ^= FCURVE_PROTECTED; + notifierFlags |= ND_ANIMCHAN_EDIT; + } } else if (x >= (ACHANNEL_NAMEWIDTH-2*ACHANNEL_BUTTON_WIDTH)) { /* toggle mute */ fcu->flag ^= FCURVE_MUTED; + notifierFlags |= ND_ANIMCHAN_EDIT; } else if ((x < (offset+17)) && (ac->spacetype==SPACE_IPO)) { /* toggle visibility */ fcu->flag ^= FCURVE_VISIBLE; + notifierFlags |= ND_ANIMCHAN_EDIT; } else { /* select/deselect */ @@ -1582,6 +1613,8 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s /* if F-Curve is selected now, make F-Curve the 'active' one in the visible list */ if (fcu->flag & FCURVE_SELECTED) ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ANIMTYPE_FCURVE); + + notifierFlags |= ND_ANIMCHAN_SELECT; } } break; @@ -1591,6 +1624,8 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s /* toggle expand */ gpd->flag ^= GP_DATA_EXPAND; + + notifierFlags |= ND_ANIMCHAN_EDIT; } break; case ANIMTYPE_GPLAYER: @@ -1629,6 +1664,9 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s /* free channels */ BLI_freelistN(&anim_data); + + /* return notifier flags */ + return notifierFlags; } /* ------------------- */ @@ -1641,6 +1679,7 @@ static int animchannels_mouseclick_invoke(bContext *C, wmOperator *op, wmEvent * ARegion *ar; View2D *v2d; int mval[2], channel_index; + int notifierFlags = 0; short selectmode; float x, y; @@ -1675,10 +1714,10 @@ static int animchannels_mouseclick_invoke(bContext *C, wmOperator *op, wmEvent * UI_view2d_listview_view_to_cell(v2d, ACHANNEL_NAMEWIDTH, ACHANNEL_STEP, 0, (float)ACHANNEL_HEIGHT_HALF, x, y, NULL, &channel_index); /* handle mouse-click in the relevant channel then */ - mouse_anim_channels(&ac, x, channel_index, selectmode); + notifierFlags= mouse_anim_channels(&ac, x, channel_index, selectmode); - /* set notifier tha things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_CHANNELS); + /* set notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION|notifierFlags, NULL); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/animation/anim_deps.c b/source/blender/editors/animation/anim_deps.c index 1ff2169bf61..13667159fe0 100644 --- a/source/blender/editors/animation/anim_deps.c +++ b/source/blender/editors/animation/anim_deps.c @@ -77,72 +77,6 @@ void ED_anim_object_flush_update(const bContext *C, Object *ob) } -/* **************************** animation tool notifiers ******************************** */ - -/* Send notifiers on behalf of animation editing tools, based on various context info - * - data_changed: eAnimData_Changed - */ -void ANIM_animdata_send_notifiers (bContext *C, bAnimContext *ac, short data_changed) -{ - /* types of notifiers to send, depends on the editor context */ - switch (ac->datatype) { - case ANIMCONT_DOPESHEET: /* dopesheet */ - case ANIMCONT_FCURVES: /* fcurve editor */ - case ANIMCONT_DRIVERS: /* drivers editor */ // XXX probably this will need separate handling, since these are part of dependency system - { - /* what action was taken */ - switch (data_changed) { - case ANIM_CHANGED_KEYFRAMES_VALUES: - /* keyframe values changed, so transform may have changed */ - // XXX what about other cases? maybe we need general ND_KEYFRAMES or ND_ANIMATION? - WM_event_add_notifier(C, NC_OBJECT|ND_KEYS|ND_TRANSFORM, NULL); - break; - case ANIM_CHANGED_KEYFRAMES_SELECT: - WM_event_add_notifier(C, NC_OBJECT|ND_KEYS, NULL); - break; - case ANIM_CHANGED_CHANNELS: - // XXX err... check available datatypes in dopesheet first? - // FIXME: this currently doesn't work (to update own view) - WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE|ND_OB_SELECT, ac->scene); - WM_event_add_notifier(C, NC_OBJECT|ND_BONE_ACTIVE|ND_BONE_SELECT, NULL); - break; - } - - // XXX for now, at least update own editor! - ED_area_tag_redraw(CTX_wm_area(C)); - } - break; - - case ANIMCONT_ACTION: /* action editor */ - { - Object *obact= CTX_data_active_object(C); - - switch (data_changed) { - case ANIM_CHANGED_KEYFRAMES_VALUES: - /* keyframe values changed, so transform may have changed */ - // XXX what about other cases? maybe we need general ND_KEYFRAMES or ND_ANIMATION? - WM_event_add_notifier(C, NC_OBJECT|ND_KEYS|ND_TRANSFORM, obact); - break; - case ANIM_CHANGED_KEYFRAMES_SELECT: - WM_event_add_notifier(C, NC_OBJECT|ND_KEYS, obact); - break; - case ANIM_CHANGED_CHANNELS: - // XXX err... check available datatypes in dopesheet first? - // FIXME: this currently doesn't work (to update own view) - WM_event_add_notifier(C, NC_OBJECT|ND_BONE_ACTIVE|ND_BONE_SELECT, obact); - break; - } - - // XXX for now, at least update own editor! - ED_area_tag_redraw(CTX_wm_area(C)); - } - break; - - default: /* some other data... just update area for now */ - ED_area_tag_redraw(CTX_wm_area(C)); - } -} - /* **************************** pose <-> action syncing ******************************** */ /* Summary of what needs to be synced between poses and actions: * 1) Flags @@ -152,6 +86,10 @@ void ANIM_animdata_send_notifiers (bContext *C, bAnimContext *ac, short data_cha * 3) Grouping (only for pose to action for now) */ +/* XXX OBSOLETE CODE WARNING: + * With the Animato system, the code below is somewhat obsolete now... + */ + /* Notifier from Action/Dopesheet (this may be extended to include other things such as Python...) * Channels in action changed, so update pose channels/groups to reflect changes. * diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c index 48ca06fb73d..6e62b163ca9 100644 --- a/source/blender/editors/animation/keyframes_general.c +++ b/source/blender/editors/animation/keyframes_general.c @@ -52,6 +52,8 @@ #include "ED_keyframing.h" #include "ED_keyframes_edit.h" +#include "RNA_access.h" + /* This file contains code for various keyframe-editing tools which are 'destructive' * (i.e. they will modify the order of the keyframes, and change the size of the array). * While some of these tools may eventually be moved out into blenkernel, for now, it is diff --git a/source/blender/editors/animation/keyingsets.c b/source/blender/editors/animation/keyingsets.c index 240089d26a6..0f8de7f607d 100644 --- a/source/blender/editors/animation/keyingsets.c +++ b/source/blender/editors/animation/keyingsets.c @@ -1085,6 +1085,9 @@ int modify_keyframes (bContext *C, ListBase *dsources, bAction *act, KeyingSet * case ID_MA: /* Material Keyframes */ WM_event_add_notifier(C, NC_MATERIAL|ND_KEYS, ksp->id); break; + default: /* Any keyframes */ + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL); + break; } } } @@ -1191,6 +1194,9 @@ int modify_keyframes (bContext *C, ListBase *dsources, bAction *act, KeyingSet * case ID_MA: /* Material Keyframes */ WM_event_add_notifier(C, NC_MATERIAL|ND_KEYS, cks->id); break; + default: /* Any keyframes */ + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL); + break; } } } diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index 2745be978d2..cc18c81fe51 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -315,7 +315,6 @@ void ANIM_draw_previewrange(const struct bContext *C, struct View2D *v2d); struct uiLayout; /* draw a given F-Modifier for some layout/UI-Block */ -// XXX not quite complete yet void ANIM_uiTemplate_fmodifier_draw(struct uiLayout *layout, struct ID *id, ListBase *modifiers, struct FModifier *fcm); /* ************************************************* */ @@ -385,18 +384,6 @@ void ED_anim_object_flush_update(const struct bContext *C, struct Object *ob); void ANIM_action_to_pose_sync(struct Object *ob); void ANIM_pose_to_action_sync(struct Object *ob, struct ScrArea *sa); - -/* what types of animation data was changed (for sending notifiers from animation tools) */ -enum { - ANIM_CHANGED_BOTH= 0, - ANIM_CHANGED_KEYFRAMES_VALUES, - ANIM_CHANGED_KEYFRAMES_SELECT, - ANIM_CHANGED_CHANNELS -} eAnimData_Changed; - -/* Send notifiers on behalf of animation editing tools, based on various context info */ -void ANIM_animdata_send_notifiers(struct bContext *C, bAnimContext *ac, short data_changed); - /* ************************************************* */ /* OPERATORS */ diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index 04dda2e6c4c..8d2d342e28a 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -214,7 +214,7 @@ static int actkeys_viewall_exec(bContext *C, wmOperator *op) /* do View2D syncing */ UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY); - /* set notifier that things have changed */ + /* just redraw this view */ ED_area_tag_redraw(CTX_wm_area(C)); return OPERATOR_FINISHED; @@ -301,9 +301,6 @@ static int actkeys_copy_exec(bContext *C, wmOperator *op) } } - /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES); - return OPERATOR_FINISHED; } @@ -345,8 +342,8 @@ static int actkeys_paste_exec(bContext *C, wmOperator *op) /* validate keyframes after editing */ ANIM_editkeyframes_refresh(&ac); - /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES); + /* set notifier that keyframes have changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL); return OPERATOR_FINISHED; } @@ -441,8 +438,8 @@ static int actkeys_insertkey_exec(bContext *C, wmOperator *op) /* validate keyframes after editing */ ANIM_editkeyframes_refresh(&ac); - /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES); + /* set notifier that keyframes have changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL); return OPERATOR_FINISHED; } @@ -508,8 +505,8 @@ static int actkeys_duplicate_exec(bContext *C, wmOperator *op) /* validate keyframes after editing */ ANIM_editkeyframes_refresh(&ac); - /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES); + /* set notifier that keyframes have changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL); return OPERATOR_FINISHED; // xxx - start transform } @@ -585,8 +582,8 @@ static int actkeys_delete_exec(bContext *C, wmOperator *op) /* validate keyframes after editing */ ANIM_editkeyframes_refresh(&ac); - /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES); + /* set notifier that keyframes have changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL); return OPERATOR_FINISHED; } @@ -648,8 +645,8 @@ static int actkeys_clean_exec(bContext *C, wmOperator *op) /* validate keyframes after editing */ ANIM_editkeyframes_refresh(&ac); - /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES); + /* set notifier that keyframes have changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL); return OPERATOR_FINISHED; } @@ -772,8 +769,8 @@ static int actkeys_sample_exec(bContext *C, wmOperator *op) /* validate keyframes after editing */ ANIM_editkeyframes_refresh(&ac); - /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES); + /* set notifier that keyframes have changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL); return OPERATOR_FINISHED; } @@ -847,8 +844,8 @@ static int actkeys_expo_exec(bContext *C, wmOperator *op) /* validate keyframes after editing */ ANIM_editkeyframes_refresh(&ac); - /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES); + /* set notifier that keyframe properties have changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_PROP, NULL); return OPERATOR_FINISHED; } @@ -917,8 +914,8 @@ static int actkeys_ipo_exec(bContext *C, wmOperator *op) /* validate keyframes after editing */ ANIM_editkeyframes_refresh(&ac); - /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES); + /* set notifier that keyframe properties have changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_PROP, NULL); return OPERATOR_FINISHED; } @@ -1005,8 +1002,8 @@ static int actkeys_handletype_exec(bContext *C, wmOperator *op) /* validate keyframes after editing */ ANIM_editkeyframes_refresh(&ac); - /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES); + /* set notifier that keyframe properties have changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_PROP, NULL); return OPERATOR_FINISHED; } @@ -1169,8 +1166,8 @@ static int actkeys_snap_exec(bContext *C, wmOperator *op) /* validate keyframes after editing */ ANIM_editkeyframes_refresh(&ac); - /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES); + /* set notifier that keyframes have changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL); return OPERATOR_FINISHED; } @@ -1285,8 +1282,8 @@ static int actkeys_mirror_exec(bContext *C, wmOperator *op) /* validate keyframes after editing */ ANIM_editkeyframes_refresh(&ac); - /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES); + /* set notifier that keyframes have changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c index 8f95f5ea52d..d9e6bb10ceb 100644 --- a/source/blender/editors/space_action/action_select.c +++ b/source/blender/editors/space_action/action_select.c @@ -174,8 +174,8 @@ static int actkeys_deselectall_exec(bContext *C, wmOperator *op) else deselect_action_keys(&ac, 1, SELECT_ADD); - /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); + /* set notifier that keyframe selection have changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_SELECT, NULL); return OPERATOR_FINISHED; } @@ -337,6 +337,9 @@ static int actkeys_borderselect_exec(bContext *C, wmOperator *op) /* apply borderselect action */ borderselect_action(&ac, rect, mode, selectmode); + /* set notifier that keyframe selection have changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_SELECT, NULL); + return OPERATOR_FINISHED; } @@ -551,8 +554,8 @@ static int actkeys_columnselect_exec(bContext *C, wmOperator *op) else columnselect_action_keys(&ac, mode); - /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_SELECT); + /* set notifier that keyframe selection have changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_SELECT, NULL); return OPERATOR_FINISHED; } @@ -954,8 +957,8 @@ static int actkeys_clickselect_invoke(bContext *C, wmOperator *op, wmEvent *even mouse_action_keys(&ac, mval, selectmode, column); } - /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); + /* set notifier that keyframe selection (and channels too) have changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_SELECT|ND_ANIMCHAN_SELECT, NULL); /* for tweak grab to work */ return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH; diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c index b4e43c29c3d..0b06499693c 100644 --- a/source/blender/editors/space_action/space_action.c +++ b/source/blender/editors/space_action/space_action.c @@ -288,6 +288,9 @@ static void action_channel_area_listener(ARegion *ar, wmNotifier *wmn) { /* context changes */ switch(wmn->category) { + case NC_ANIMATION: + ED_region_tag_redraw(ar); + break; case NC_SCENE: switch(wmn->data) { case ND_OB_ACTIVE: @@ -314,6 +317,9 @@ static void action_main_area_listener(ARegion *ar, wmNotifier *wmn) { /* context changes */ switch(wmn->category) { + case NC_ANIMATION: + ED_region_tag_redraw(ar); + break; case NC_SCENE: switch(wmn->data) { case ND_OB_ACTIVE: @@ -344,6 +350,9 @@ static void action_listener(ScrArea *sa, wmNotifier *wmn) { /* context changes */ switch (wmn->category) { + case NC_ANIMATION: + ED_area_tag_refresh(sa); + break; case NC_SCENE: /*switch (wmn->data) { case ND_OB_ACTIVE: diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index 86970f3565c..1837b6d4ecd 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -474,8 +474,8 @@ static int graphkeys_insertkey_exec(bContext *C, wmOperator *op) /* validate keyframes after editing */ ANIM_editkeyframes_refresh(&ac); - /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES); + /* set notifier that keyframes have changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL); return OPERATOR_FINISHED; } @@ -532,8 +532,8 @@ static int graphkeys_click_insert_exec (bContext *C, wmOperator *op) /* free temp data */ MEM_freeN(ale); - /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES); + /* set notifier that keyframes have changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL); /* done */ return OPERATOR_FINISHED; @@ -644,9 +644,7 @@ static int graphkeys_copy_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES); - + /* just return - no operator needed here (no changes) */ return OPERATOR_FINISHED; } @@ -683,8 +681,8 @@ static int graphkeys_paste_exec(bContext *C, wmOperator *op) /* validate keyframes after editing */ ANIM_editkeyframes_refresh(&ac); - /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES); + /* set notifier that keyframes have changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL); return OPERATOR_FINISHED; } @@ -740,8 +738,8 @@ static int graphkeys_duplicate_exec(bContext *C, wmOperator *op) /* validate keyframes after editing */ ANIM_editkeyframes_refresh(&ac); - /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES); + /* set notifier that keyframes have changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL); return OPERATOR_FINISHED; } @@ -811,8 +809,8 @@ static int graphkeys_delete_exec(bContext *C, wmOperator *op) /* validate keyframes after editing */ ANIM_editkeyframes_refresh(&ac); - /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES); + /* set notifier that keyframes have changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL); return OPERATOR_FINISHED; } @@ -872,8 +870,8 @@ static int graphkeys_clean_exec(bContext *C, wmOperator *op) /* validate keyframes after editing */ ANIM_editkeyframes_refresh(&ac); - /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES); + /* set notifier that keyframes have changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL); return OPERATOR_FINISHED; } @@ -953,8 +951,9 @@ static int graphkeys_bake_exec(bContext *C, wmOperator *op) /* validate keyframes after editing */ ANIM_editkeyframes_refresh(&ac); - /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES); + /* set notifier that keyframes have changed */ + // NOTE: some distinction between order/number of keyframes and type should be made? + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL); return OPERATOR_FINISHED; } @@ -1079,8 +1078,8 @@ static int graphkeys_sample_exec(bContext *C, wmOperator *op) /* validate keyframes after editing */ ANIM_editkeyframes_refresh(&ac); - /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES); + /* set notifier that keyframes have changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL); return OPERATOR_FINISHED; } @@ -1153,8 +1152,8 @@ static int graphkeys_expo_exec(bContext *C, wmOperator *op) /* validate keyframes after editing */ ANIM_editkeyframes_refresh(&ac); - /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES); + /* set notifier that keyframe properties have changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_PROP, NULL); return OPERATOR_FINISHED; } @@ -1221,8 +1220,8 @@ static int graphkeys_ipo_exec(bContext *C, wmOperator *op) /* validate keyframes after editing */ ANIM_editkeyframes_refresh(&ac); - /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES); + /* set notifier that keyframe properties have changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_PROP, NULL); return OPERATOR_FINISHED; } @@ -1309,7 +1308,7 @@ static int graphkeys_handletype_exec(bContext *C, wmOperator *op) ANIM_editkeyframes_refresh(&ac); /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES); + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_PROP, NULL); return OPERATOR_FINISHED; } @@ -1554,8 +1553,8 @@ static int graphkeys_snap_exec(bContext *C, wmOperator *op) /* validate keyframes after editing */ ANIM_editkeyframes_refresh(&ac); - /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES); + /* set notifier that keyframes have changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL); return OPERATOR_FINISHED; } @@ -1665,8 +1664,8 @@ static int graphkeys_mirror_exec(bContext *C, wmOperator *op) /* validate keyframes after editing */ ANIM_editkeyframes_refresh(&ac); - /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES); + /* set notifier that keyframes have changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL); return OPERATOR_FINISHED; } @@ -1719,8 +1718,8 @@ static int graphkeys_smooth_exec(bContext *C, wmOperator *op) /* validate keyframes after editing */ ANIM_editkeyframes_refresh(&ac); - /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES); + /* set notifier that keyframes have changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL); return OPERATOR_FINISHED; } @@ -1810,7 +1809,8 @@ static int graph_fmodifier_add_exec(bContext *C, wmOperator *op) ANIM_editkeyframes_refresh(&ac); /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); + // FIXME: this really isn't the best description for it... + WM_event_add_notifier(C, NC_ANIMATION, NULL); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c index c855222df02..a78cacb42ef 100644 --- a/source/blender/editors/space_graph/graph_select.c +++ b/source/blender/editors/space_graph/graph_select.c @@ -169,7 +169,7 @@ static int graphkeys_deselectall_exec(bContext *C, wmOperator *op) deselect_graph_keys(&ac, 1, SELECT_ADD); /* set notifier that things have changed */ - ED_area_tag_redraw(CTX_wm_area(C)); // FIXME... should be updating 'keyframes' data context or so instead! + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_SELECT, NULL); return OPERATOR_FINISHED; } @@ -302,6 +302,9 @@ static int graphkeys_borderselect_exec(bContext *C, wmOperator *op) /* apply borderselect action */ borderselect_graphkeys(&ac, rect, mode, selectmode); + /* send notifier that keyframe selection has changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_SELECT, NULL); + return OPERATOR_FINISHED; } @@ -492,8 +495,8 @@ static int graphkeys_columnselect_exec(bContext *C, wmOperator *op) else columnselect_graph_keys(&ac, mode); - /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_SELECT); + /* set notifier that keyframe selection has changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_SELECT, NULL); return OPERATOR_FINISHED; } @@ -911,8 +914,8 @@ static int graphkeys_clickselect_invoke(bContext *C, wmOperator *op, wmEvent *ev mouse_graph_keys(&ac, mval, selectmode, 0); } - /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); + /* set notifier that keyframe selection (and also channel selection in some cases) has changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_SELECT|ND_ANIMCHAN_SELECT, NULL); /* for tweak grab to work */ return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH; diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c index 2f3700bc733..a5578e88076 100644 --- a/source/blender/editors/space_graph/space_graph.c +++ b/source/blender/editors/space_graph/space_graph.c @@ -365,6 +365,9 @@ static void graph_region_listener(ARegion *ar, wmNotifier *wmn) { /* context changes */ switch(wmn->category) { + case NC_ANIMATION: + ED_region_tag_redraw(ar); + break; case NC_SCENE: switch(wmn->data) { case ND_OB_ACTIVE: @@ -395,6 +398,9 @@ static void graph_listener(ScrArea *sa, wmNotifier *wmn) { /* context changes */ switch (wmn->category) { + case NC_ANIMATION: + ED_area_tag_refresh(sa); + break; case NC_SCENE: /*switch (wmn->data) { case ND_OB_ACTIVE: diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c index 5a891a541cb..1ab348eb28e 100644 --- a/source/blender/editors/space_nla/nla_channels.c +++ b/source/blender/editors/space_nla/nla_channels.c @@ -89,11 +89,12 @@ * NOTE: eventually, this should probably be phased out when many of these things are replaced with buttons */ -static void mouse_nla_channels (bAnimContext *ac, float x, int channel_index, short selectmode) +static int mouse_nla_channels (bAnimContext *ac, float x, int channel_index, short selectmode) { ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; int filter; + int notifierFlags = 0; /* get the channel that was clicked on */ /* filter channels */ @@ -107,7 +108,7 @@ static void mouse_nla_channels (bAnimContext *ac, float x, int channel_index, sh printf("Error: animation channel (index = %d) not found in mouse_anim_channels() \n", channel_index); BLI_freelistN(&anim_data); - return; + return 0; } /* action to take depends on what channel we've got */ @@ -119,6 +120,8 @@ static void mouse_nla_channels (bAnimContext *ac, float x, int channel_index, sh if (x < 16) { /* toggle expand */ sce->flag ^= SCE_DS_COLLAPSED; + + notifierFlags |= ND_ANIMCHAN_EDIT; } else { /* set selection status */ @@ -129,6 +132,8 @@ static void mouse_nla_channels (bAnimContext *ac, float x, int channel_index, sh else { sce->flag |= SCE_DS_SELECTED; } + + notifierFlags |= ND_ANIMCHAN_SELECT; } } break; @@ -141,7 +146,8 @@ static void mouse_nla_channels (bAnimContext *ac, float x, int channel_index, sh if (x < 16) { /* toggle expand */ - ob->nlaflag ^= OB_ADS_COLLAPSED; // XXX + ob->nlaflag ^= OB_ADS_COLLAPSED; // XXX + notifierFlags |= ND_ANIMCHAN_EDIT; } else if (nlaedit_is_tweakmode_on(ac) == 0) { /* set selection status */ @@ -166,6 +172,9 @@ static void mouse_nla_channels (bAnimContext *ac, float x, int channel_index, sh /* xxx should be ED_base_object_activate(), but we need context pointer for that... */ //set_active_base(base); + + /* notifiers - channel was selected */ + notifierFlags |= ND_ANIMCHAN_SELECT; } } break; @@ -173,6 +182,7 @@ static void mouse_nla_channels (bAnimContext *ac, float x, int channel_index, sh { Object *ob= (Object *)ale->data; ob->nlaflag ^= OB_ADS_SHOWMATS; // XXX + notifierFlags |= ND_ANIMCHAN_EDIT; } break; @@ -180,36 +190,42 @@ static void mouse_nla_channels (bAnimContext *ac, float x, int channel_index, sh { Material *ma= (Material *)ale->data; ma->flag ^= MA_DS_EXPAND; + notifierFlags |= ND_ANIMCHAN_EDIT; } break; case ANIMTYPE_DSLAM: { Lamp *la= (Lamp *)ale->data; la->flag ^= LA_DS_EXPAND; + notifierFlags |= ND_ANIMCHAN_EDIT; } break; case ANIMTYPE_DSCAM: { Camera *ca= (Camera *)ale->data; ca->flag ^= CAM_DS_EXPAND; + notifierFlags |= ND_ANIMCHAN_EDIT; } break; case ANIMTYPE_DSCUR: { Curve *cu= (Curve *)ale->data; cu->flag ^= CU_DS_EXPAND; + notifierFlags |= ND_ANIMCHAN_EDIT; } break; case ANIMTYPE_DSSKEY: { Key *key= (Key *)ale->data; key->flag ^= KEYBLOCK_DS_EXPAND; + notifierFlags |= ND_ANIMCHAN_EDIT; } break; case ANIMTYPE_DSWOR: { World *wo= (World *)ale->data; wo->flag ^= WO_DS_EXPAND; + notifierFlags |= ND_ANIMCHAN_EDIT; } break; @@ -233,14 +249,23 @@ static void mouse_nla_channels (bAnimContext *ac, float x, int channel_index, sh if (x >= (NLACHANNEL_NAMEWIDTH-NLACHANNEL_BUTTON_WIDTH)) { /* toggle protection (only if there's a toggle there) */ nlt->flag ^= NLATRACK_PROTECTED; + + /* notifier flags - channel was edited */ + notifierFlags |= ND_ANIMCHAN_EDIT; } else if (x >= (NLACHANNEL_NAMEWIDTH-2*NLACHANNEL_BUTTON_WIDTH)) { /* toggle mute */ nlt->flag ^= NLATRACK_MUTED; + + /* notifier flags - channel was edited */ + notifierFlags |= ND_ANIMCHAN_EDIT; } else if (x <= ((NLACHANNEL_BUTTON_WIDTH*2)+offset)) { /* toggle 'solo' */ BKE_nlatrack_solo_toggle(adt, nlt); + + /* notifier flags - channel was edited */ + notifierFlags |= ND_ANIMCHAN_EDIT; } else if (nlaedit_is_tweakmode_on(ac) == 0) { /* set selection */ @@ -257,6 +282,9 @@ static void mouse_nla_channels (bAnimContext *ac, float x, int channel_index, sh /* if NLA-Track is selected now, make NLA-Track the 'active' one in the visible list */ if (nlt->flag & NLATRACK_SELECTED) ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, nlt, ANIMTYPE_NLATRACK); + + /* notifier flags - channel was selected */ + notifierFlags |= ND_ANIMCHAN_SELECT; } } break; @@ -275,6 +303,9 @@ static void mouse_nla_channels (bAnimContext *ac, float x, int channel_index, sh /* when in tweakmode, this button becomes the toggle for mapped editing */ adt->flag ^= ADT_NLA_EDIT_NOMAP; } + + /* changes to NLA-Action occurred */ + notifierFlags |= ND_NLA_ACTCHANGE; } } break; @@ -285,6 +316,9 @@ static void mouse_nla_channels (bAnimContext *ac, float x, int channel_index, sh /* free channels */ BLI_freelistN(&anim_data); + + /* return the notifier-flags set */ + return notifierFlags; } /* ------------------- */ @@ -297,6 +331,7 @@ static int nlachannels_mouseclick_invoke(bContext *C, wmOperator *op, wmEvent *e ARegion *ar; View2D *v2d; int mval[2], channel_index; + int notifierFlags = 0; short selectmode; float x, y; @@ -328,10 +363,10 @@ static int nlachannels_mouseclick_invoke(bContext *C, wmOperator *op, wmEvent *e UI_view2d_listview_view_to_cell(v2d, NLACHANNEL_NAMEWIDTH, NLACHANNEL_STEP, 0, (float)NLACHANNEL_HEIGHT_HALF, x, y, NULL, &channel_index); /* handle mouse-click in the relevant channel then */ - mouse_nla_channels(&ac, x, channel_index, selectmode); + notifierFlags= mouse_nla_channels(&ac, x, channel_index, selectmode); - /* set notifier tha things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_CHANNELS); + /* set notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION|notifierFlags, NULL); return OPERATOR_FINISHED; } @@ -401,8 +436,7 @@ static int nlaedit_add_tracks_exec (bContext *C, wmOperator *op) BLI_freelistN(&anim_data); /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); - WM_event_add_notifier(C, NC_SCENE, NULL); + WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_EDIT, NULL); /* done */ return OPERATOR_FINISHED; @@ -458,8 +492,7 @@ static int nlaedit_delete_tracks_exec (bContext *C, wmOperator *op) BLI_freelistN(&anim_data); /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); - WM_event_add_notifier(C, NC_SCENE, NULL); + WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_EDIT, NULL); /* done */ return OPERATOR_FINISHED; diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index 6cbc9cab253..cb151429dd1 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -127,8 +127,7 @@ static int nlaedit_enable_tweakmode_exec (bContext *C, wmOperator *op) ac.scene->flag |= SCE_NLA_EDIT_ON; /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); - WM_event_add_notifier(C, NC_SCENE, NULL); + WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_ACTCHANGE, NULL); } else { BKE_report(op->reports, RPT_ERROR, "No active strip(s) to enter tweakmode on."); @@ -197,8 +196,7 @@ static int nlaedit_disable_tweakmode_exec (bContext *C, wmOperator *op) ac.scene->flag &= ~SCE_NLA_EDIT_ON; /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); - WM_event_add_notifier(C, NC_SCENE, NULL); + WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_ACTCHANGE, NULL); } /* done */ @@ -315,8 +313,7 @@ static int nlaedit_add_actionclip_exec (bContext *C, wmOperator *op) BLI_freelistN(&anim_data); /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); - WM_event_add_notifier(C, NC_SCENE, NULL); + WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_EDIT, NULL); /* done */ return OPERATOR_FINISHED; @@ -424,8 +421,7 @@ static int nlaedit_add_transition_exec (bContext *C, wmOperator *op) /* was anything added? */ if (done) { /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); - WM_event_add_notifier(C, NC_SCENE, NULL); + WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_EDIT, NULL); /* done */ return OPERATOR_FINISHED; @@ -483,8 +479,7 @@ static int nlaedit_add_meta_exec (bContext *C, wmOperator *op) BLI_freelistN(&anim_data); /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); - WM_event_add_notifier(C, NC_SCENE, NULL); + WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_EDIT, NULL); /* done */ return OPERATOR_FINISHED; @@ -536,8 +531,7 @@ static int nlaedit_remove_meta_exec (bContext *C, wmOperator *op) BLI_freelistN(&anim_data); /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); - WM_event_add_notifier(C, NC_SCENE, NULL); + WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_EDIT, NULL); /* done */ return OPERATOR_FINISHED; @@ -621,8 +615,7 @@ static int nlaedit_duplicate_exec (bContext *C, wmOperator *op) if (done) { /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); - WM_event_add_notifier(C, NC_SCENE, NULL); + WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_EDIT, NULL); /* done */ return OPERATOR_FINISHED; @@ -707,8 +700,7 @@ static int nlaedit_delete_exec (bContext *C, wmOperator *op) BLI_freelistN(&anim_data); /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); - WM_event_add_notifier(C, NC_SCENE, NULL); + WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_EDIT, NULL); /* done */ return OPERATOR_FINISHED; @@ -831,8 +823,7 @@ static int nlaedit_split_exec (bContext *C, wmOperator *op) BLI_freelistN(&anim_data); /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); - WM_event_add_notifier(C, NC_SCENE, NULL); + WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_EDIT, NULL); /* done */ return OPERATOR_FINISHED; @@ -894,8 +885,7 @@ static int nlaedit_toggle_mute_exec (bContext *C, wmOperator *op) BLI_freelistN(&anim_data); /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); - WM_event_add_notifier(C, NC_SCENE, NULL); + WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_EDIT, NULL); /* done */ return OPERATOR_FINISHED; @@ -966,8 +956,7 @@ static int nlaedit_move_up_exec (bContext *C, wmOperator *op) BLI_freelistN(&anim_data); /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); - WM_event_add_notifier(C, NC_SCENE, NULL); + WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_EDIT, NULL); /* done */ return OPERATOR_FINISHED; @@ -1038,8 +1027,7 @@ static int nlaedit_move_down_exec (bContext *C, wmOperator *op) BLI_freelistN(&anim_data); /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); - WM_event_add_notifier(C, NC_SCENE, NULL); + WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_EDIT, NULL); /* done */ return OPERATOR_FINISHED; @@ -1137,8 +1125,7 @@ static int nlaedit_apply_scale_exec (bContext *C, wmOperator *op) BLI_freelistN(&anim_data); /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); - WM_event_add_notifier(C, NC_SCENE, NULL); + WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_EDIT, NULL); /* done */ return OPERATOR_FINISHED; @@ -1198,8 +1185,7 @@ static int nlaedit_clear_scale_exec (bContext *C, wmOperator *op) BLI_freelistN(&anim_data); /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); - WM_event_add_notifier(C, NC_SCENE, NULL); + WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_EDIT, NULL); /* done */ return OPERATOR_FINISHED; @@ -1337,8 +1323,7 @@ static int nlaedit_snap_exec (bContext *C, wmOperator *op) BLI_freelistN(&anim_data); /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); - WM_event_add_notifier(C, NC_SCENE, NULL); + WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_EDIT, NULL); /* done */ return OPERATOR_FINISHED; @@ -1447,8 +1432,8 @@ static int nla_fmodifier_add_exec(bContext *C, wmOperator *op) BLI_freelistN(&anim_data); /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); - WM_event_add_notifier(C, NC_SCENE, NULL); + // FIXME: this doesn't really do it justice... + WM_event_add_notifier(C, NC_ANIMATION, NULL); /* done */ return OPERATOR_FINISHED; diff --git a/source/blender/editors/space_nla/nla_select.c b/source/blender/editors/space_nla/nla_select.c index 895d0dbf88a..dd9ef2621c5 100644 --- a/source/blender/editors/space_nla/nla_select.c +++ b/source/blender/editors/space_nla/nla_select.c @@ -186,7 +186,7 @@ static int nlaedit_deselectall_exec(bContext *C, wmOperator *op) deselect_nla_strips(&ac, DESELECT_STRIPS_TEST, SELECT_ADD); /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); + WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_SELECT, NULL); return OPERATOR_FINISHED; } @@ -324,6 +324,9 @@ static int nlaedit_borderselect_exec(bContext *C, wmOperator *op) /* apply borderselect action */ borderselect_nla_strips(&ac, rect, mode, selectmode); + /* set notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_SELECT, NULL); + return OPERATOR_FINISHED; } @@ -583,7 +586,7 @@ static int nlaedit_clickselect_invoke(bContext *C, wmOperator *op, wmEvent *even } /* set notifier that things have changed */ - ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH); + WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_SELECT, NULL); /* for tweak grab to work */ return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH; diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c index a7e9844726d..923208f3b35 100644 --- a/source/blender/editors/space_nla/space_nla.c +++ b/source/blender/editors/space_nla/space_nla.c @@ -371,6 +371,9 @@ static void nla_region_listener(ARegion *ar, wmNotifier *wmn) { /* context changes */ switch(wmn->category) { + case NC_ANIMATION: + ED_region_tag_redraw(ar); + break; case NC_SCENE: switch(wmn->data) { case ND_OB_ACTIVE: @@ -392,7 +395,7 @@ static void nla_region_listener(ARegion *ar, wmNotifier *wmn) default: if(wmn->data==ND_KEYS) ED_region_tag_redraw(ar); - + break; } } @@ -401,6 +404,9 @@ static void nla_main_area_listener(ARegion *ar, wmNotifier *wmn) { /* context changes */ switch(wmn->category) { + case NC_ANIMATION: + ED_region_tag_redraw(ar); + break; case NC_SCENE: switch(wmn->data) { case ND_OB_ACTIVE: @@ -430,6 +436,9 @@ static void nla_channel_area_listener(ARegion *ar, wmNotifier *wmn) { /* context changes */ switch(wmn->category) { + case NC_ANIMATION: + ED_region_tag_redraw(ar); + break; case NC_SCENE: switch(wmn->data) { case ND_OB_ACTIVE: @@ -457,6 +466,10 @@ static void nla_listener(ScrArea *sa, wmNotifier *wmn) { /* context changes */ switch (wmn->category) { + case NC_ANIMATION: + // TODO: filter specific types of changes? + ED_area_tag_refresh(sa); + break; case NC_SCENE: /*switch (wmn->data) { case ND_OB_ACTIVE: diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index f3797ec308b..6c3bb798c18 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -409,6 +409,15 @@ static void view3d_main_area_listener(ARegion *ar, wmNotifier *wmn) { /* context changes */ switch(wmn->category) { + case NC_ANIMATION: + switch(wmn->data) { + case ND_KEYFRAME_EDIT: + case ND_KEYFRAME_PROP: + case ND_NLA_ACTCHANGE: + case ND_ANIMCHAN_SELECT: + ED_region_tag_redraw(ar); + break; + } case NC_SCENE: switch(wmn->data) { case ND_TRANSFORM: diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 368730b1cfa..016400e0fa9 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -300,27 +300,15 @@ static void viewRedrawForce(bContext *C, TransInfo *t) WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL); } else if (t->spacetype == SPACE_ACTION) { - SpaceAction *saction= (SpaceAction *)t->sa->spacedata.first; - - // TRANSFORM_FIX_ME - if (saction->lock) { - // whole window... - } - else - ED_area_tag_redraw(t->sa); + //SpaceAction *saction= (SpaceAction *)t->sa->spacedata.first; + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL); } else if (t->spacetype == SPACE_IPO) { - SpaceIpo *sipo= (SpaceIpo *)t->sa->spacedata.first; - - // TRANSFORM_FIX_ME - if (sipo->lock) { - // whole window... - } - else - ED_area_tag_redraw(t->sa); + //SpaceIpo *sipo= (SpaceIpo *)t->sa->spacedata.first; + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL); } else if (t->spacetype == SPACE_NLA) { - ED_area_tag_redraw(t->sa); // XXX this should use a notifier instead! + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL); } else if(t->spacetype == SPACE_NODE) { diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index e3a7a906fef..432140f1cf7 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -129,6 +129,7 @@ typedef struct wmNotifier { #define NC_TEXT (12<<24) #define NC_WORLD (13<<24) #define NC_FILE (14<<24) +#define NC_ANIMATION (15<<24) /* data type, 256 entries is enough, it can overlap */ #define NOTE_DATA 0x00FF0000 @@ -188,6 +189,16 @@ typedef struct wmNotifier { #define ND_PARAMS (60<<16) #define ND_FILELIST (61<<16) + /* NC_ANIMATION Animato */ +#define ND_KEYFRAME_SELECT (70<<16) +#define ND_KEYFRAME_EDIT (71<<16) +#define ND_KEYFRAME_PROP (72<<16) +#define ND_ANIMCHAN_SELECT (73<<16) +#define ND_ANIMCHAN_EDIT (74<<16) +#define ND_NLA_SELECT (75<<16) +#define ND_NLA_EDIT (76<<16) +#define ND_NLA_ACTCHANGE (77<<16) + /* subtype, 256 entries too */ #define NOTE_SUBTYPE 0x0000FF00 From d6ef4380a0d23acb619018fdaf84f5381b71f325 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 10 Jul 2009 12:11:00 +0000 Subject: [PATCH 111/114] NLA SoC: Delete Channels operator F-Curves and Groups can now be deleted again from DopeSheet/Graph Editors. --- .../blender/editors/animation/anim_channels.c | 148 +++++++++++++++++- 1 file changed, 142 insertions(+), 6 deletions(-) diff --git a/source/blender/editors/animation/anim_channels.c b/source/blender/editors/animation/anim_channels.c index 1cf553f6f26..5c31d007705 100644 --- a/source/blender/editors/animation/anim_channels.c +++ b/source/blender/editors/animation/anim_channels.c @@ -63,9 +63,10 @@ #include "RNA_access.h" #include "RNA_define.h" +#include "BKE_animsys.h" #include "BKE_action.h" #include "BKE_depsgraph.h" -#include "BKE_ipo.h" +#include "BKE_fcurve.h" #include "BKE_key.h" #include "BKE_material.h" #include "BKE_object.h" @@ -133,7 +134,7 @@ void ANIM_set_active_channel (bAnimContext *ac, void *data, short datatype, int } /* set active flag */ - if (channel_data) { + if (channel_data != NULL) { switch (channel_type) { case ANIMTYPE_GROUP: { @@ -691,6 +692,121 @@ void ANIM_OT_channels_move_bottom (wmOperatorType *ot) #endif // XXX old animation system - needs to be updated for new system... +/* ******************** Delete Channel Operator *********************** */ + +static int animchannels_delete_exec(bContext *C, wmOperator *op) +{ + bAnimContext ac; + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* cannot delete in shapekey */ + if (ac.datatype == ANIMCONT_SHAPEKEY) + return OPERATOR_CANCELLED; + + + /* do groups only first (unless in Drivers mode, where there are none) */ + if (ac.datatype != ANIMCONT_DRIVERS) { + /* filter data */ + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_CHANNELS | ANIMFILTER_FOREDIT); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* delete selected groups and their associated channels */ + for (ale= anim_data.first; ale; ale= ale->next) { + /* only groups - don't check other types yet, since they may no-longer exist */ + if (ale->type == ANIMTYPE_GROUP) { + bActionGroup *agrp= (bActionGroup *)ale->data; + AnimData *adt= BKE_animdata_from_id(ale->id); + FCurve *fcu, *fcn; + + /* skip this group if no AnimData available, as we can't safely remove the F-Curves */ + if (adt == NULL) + continue; + + /* delete all of the Group's F-Curves, but no others */ + for (fcu= agrp->channels.first; fcu && fcu->grp==agrp; fcu= fcn) { + fcn= fcu->next; + + /* remove from group and action, then free */ + action_groups_remove_channel(adt->action, fcu); + free_fcurve(fcu); + } + + /* free the group itself */ + if (adt->action) + BLI_freelinkN(&adt->action->groups, agrp); + else + MEM_freeN(agrp); + } + } + + /* cleanup */ + BLI_freelistN(&anim_data); + } + + /* now do F-Curves */ + if (ac.datatype != ANIMCONT_GPENCIL) { + /* filter data */ + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* delete selected F-Curves */ + for (ale= anim_data.first; ale; ale= ale->next) { + /* only F-Curves, and only if we can identify its parent */ + if (ale->type == ANIMTYPE_FCURVE) { + AnimData *adt= BKE_animdata_from_id(ale->id); + FCurve *fcu= (FCurve *)ale->data; + + /* if no AnimData, we've got nowhere to remove the F-Curve from */ + if (adt == NULL) + continue; + + /* remove from whatever list it came from + * - Action Group + * - Action + * - Drivers + * - TODO... some others? + */ + if (fcu->grp) + action_groups_remove_channel(adt->action, fcu); + else if (adt->action) + BLI_remlink(&adt->action->curves, fcu); + else if (ac.datatype == ANIMCONT_DRIVERS) + BLI_remlink(&adt->drivers, fcu); + + /* free the F-Curve itself */ + free_fcurve(fcu); + } + } + + /* cleanup */ + BLI_freelistN(&anim_data); + } + + /* send notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_EDIT, NULL); + + return OPERATOR_FINISHED; +} + +void ANIM_OT_channels_delete (wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Delete Channels"; + ot->idname= "ANIM_OT_channels_delete"; + + /* api callbacks */ + ot->exec= animchannels_delete_exec; + ot->poll= animedit_poll_channels_active; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} /* ******************** Toggle Channel Visibility Operator *********************** */ @@ -707,7 +823,7 @@ static int animchannels_visibility_toggle_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; /* filter data */ - filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_CURVESONLY); + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL); ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); /* See if we should be making showing all selected or hiding */ @@ -715,14 +831,28 @@ static int animchannels_visibility_toggle_exec(bContext *C, wmOperator *op) if (vis == ACHANNEL_SETFLAG_CLEAR) break; - if (ale->flag & FCURVE_VISIBLE) + if ((ale->type == ANIMTYPE_FCURVE) && (ale->flag & FCURVE_VISIBLE)) + vis= ACHANNEL_SETFLAG_CLEAR; + else if ((ale->type == ANIMTYPE_GROUP) && !(ale->flag & AGRP_NOTVISIBLE)) vis= ACHANNEL_SETFLAG_CLEAR; } /* Now set the flags */ for (ale= anim_data.first; ale; ale= ale->next) { - FCurve *fcu= (FCurve *)ale->data; - ACHANNEL_SET_FLAG(fcu, vis, FCURVE_VISIBLE); + switch (ale->type) { + case ANIMTYPE_FCURVE: /* F-Curve */ + { + FCurve *fcu= (FCurve *)ale->data; + ACHANNEL_SET_FLAG(fcu, vis, FCURVE_VISIBLE); + } + break; + case ANIMTYPE_GROUP: /* Group */ + { + bActionGroup *agrp= (bActionGroup *)ale->data; + ACHANNEL_SET_FLAG_NEG(agrp, vis, AGRP_NOTVISIBLE); + } + break; + } } /* cleanup */ @@ -1753,6 +1883,8 @@ void ED_operatortypes_animchannels(void) WM_operatortype_append(ANIM_OT_channels_setting_disable); WM_operatortype_append(ANIM_OT_channels_setting_toggle); + WM_operatortype_append(ANIM_OT_channels_delete); + // XXX does this need to be a separate operator? WM_operatortype_append(ANIM_OT_channels_editable_toggle); @@ -1786,6 +1918,10 @@ void ED_keymap_animchannels(wmWindowManager *wm) /* borderselect */ WM_keymap_add_item(keymap, "ANIM_OT_channels_select_border", BKEY, KM_PRESS, 0, 0); + /* delete */ + WM_keymap_add_item(keymap, "ANIM_OT_channels_delete", XKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "ANIM_OT_channels_delete", DELKEY, KM_PRESS, 0, 0); + /* settings */ WM_keymap_add_item(keymap, "ANIM_OT_channels_setting_toggle", WKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "ANIM_OT_channels_setting_enable", WKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0); From b609f2aa790e122504aad34512d08241c2e01079 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 10 Jul 2009 12:42:17 +0000 Subject: [PATCH 112/114] NLA SoC: Attempt at solving the jumping-views problem The 'jumping-views' problem affected the NLA and DopeSheet editors, whereby the channels-list and the data-area would get out of sync (vertically) due to the size calculations of the two being done differently. --- source/blender/editors/space_action/action_draw.c | 2 ++ source/blender/editors/space_nla/nla_draw.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c index 93d061e8bf3..2fd5b9bbd93 100644 --- a/source/blender/editors/space_action/action_draw.c +++ b/source/blender/editors/space_action/action_draw.c @@ -422,6 +422,8 @@ void draw_channel_names(bAnimContext *ac, SpaceAction *saction, ARegion *ar) */ v2d->tot.ymin= (float)(-height); } + /* need to do a view-sync here, so that the keys area doesn't jump around */ + UI_view2d_sync(NULL, ac->sa, v2d, V2D_VIEWSYNC_AREA_VERTICAL); /* loop through channels, and set up drawing depending on their type */ y= (float)ACHANNEL_FIRST; diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index 6219acf6fae..7fb15c62277 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -512,6 +512,8 @@ void draw_nla_main_data (bAnimContext *ac, SpaceNla *snla, ARegion *ar) * (NOTE: this is ok here, the configuration is pretty straightforward) */ v2d->tot.ymin= (float)(-height); + /* need to do a view-sync here, so that the strips area doesn't jump around */ + UI_view2d_sync(NULL, ac->sa, v2d, V2D_VIEWSYNC_AREA_VERTICAL); /* loop through channels, and set up drawing depending on their type */ y= (float)(-NLACHANNEL_HEIGHT); From 66a81a4062b8cc01452316c8eeb442b0acf2663e Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 10 Jul 2009 23:25:30 +0000 Subject: [PATCH 113/114] NLA SoC: Names for NLA Strips In order to be able to better identify NLA Strips (and to reduce the complexity of the text on them), I've implemented a name property for the strips. The names are made to be unique within the AnimData block the strip comes from, though this may not always happen if not enough relevant context info is present to validate this. --- source/blender/blenkernel/BKE_nla.h | 4 + source/blender/blenkernel/intern/nla.c | 93 ++++++++++++++++++- .../blender/editors/space_nla/nla_buttons.c | 3 +- source/blender/editors/space_nla/nla_draw.c | 25 +---- source/blender/editors/space_nla/nla_edit.c | 31 ++++++- source/blender/makesdna/DNA_anim_types.h | 2 + source/blender/makesrna/intern/rna_nla.c | 22 +++++ 7 files changed, 152 insertions(+), 28 deletions(-) diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index 04d4b0f8da2..bb5a2782663 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -83,6 +83,10 @@ struct NlaStrip *BKE_nlastrip_find_active(struct NlaTrack *nlt); short BKE_nlastrip_within_bounds(struct NlaStrip *strip, float min, float max); +void BKE_nlastrip_validate_name(struct AnimData *adt, struct NlaStrip *strip); + +/* ............ */ + short BKE_nlatrack_has_animated_strips(struct NlaTrack *nlt); short BKE_nlatracks_have_animated_strips(ListBase *tracks); void BKE_nlastrip_validate_fcurves(struct NlaStrip *strip); diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index c697f639021..a240de209d9 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -30,12 +30,14 @@ #include #include #include +#include #include #include #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" +#include "BLI_ghash.h" #include "DNA_anim_types.h" #include "DNA_action_types.h" @@ -326,6 +328,9 @@ NlaStrip *add_nlastrip_to_stack (AnimData *adt, bAction *act) BKE_nlatrack_add_strip(nlt, strip); } + /* automatically name it too */ + BKE_nlastrip_validate_name(adt, strip); + /* returns the strip added */ return strip; } @@ -503,7 +508,7 @@ float BKE_nla_tweakedit_remap (AnimData *adt, float cframe, short mode) } /* *************************************************** */ -/* Basic Utilities */ +/* NLA API */ /* List of Strips ------------------------------------ */ /* (these functions are used for NLA-Tracks and also for nested/meta-strips) */ @@ -1140,8 +1145,90 @@ void BKE_nlastrip_validate_fcurves (NlaStrip *strip) } } } - -/* Tools ------------------------------------------- */ + +/* Sanity Validation ------------------------------------ */ + +/* Find (and set) a unique name for a strip from the whole AnimData block + * Uses a similar method to the BLI method, but is implemented differently + * as we need to ensure that the name is unique over several lists of tracks, + * not just a single track. + */ +void BKE_nlastrip_validate_name (AnimData *adt, NlaStrip *strip) +{ + GHash *gh; + NlaStrip *tstrip; + NlaTrack *nlt; + + /* sanity checks */ + if ELEM(NULL, adt, strip) + return; + + /* give strip a default name if none already */ + if (strip->name[0]==0) { + switch (strip->type) { + case NLASTRIP_TYPE_CLIP: /* act-clip */ + sprintf(strip->name, "Act: %s", (strip->act)?(strip->act->id.name+2):("")); + break; + case NLASTRIP_TYPE_TRANSITION: /* transition */ + sprintf(strip->name, "Transition"); + break; + case NLASTRIP_TYPE_META: /* meta */ + sprintf(strip->name, "Meta"); + break; + default: + sprintf(strip->name, "NLA Strip"); + break; + } + } + + /* build a hash-table of all the strips in the tracks + * - this is easier than iterating over all the tracks+strips hierarchy everytime + * (and probably faster) + */ + gh= BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp); + + for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) { + for (tstrip= nlt->strips.first; tstrip; tstrip= tstrip->next) { + /* don't add the strip of interest */ + if (tstrip == strip) + continue; + + /* use the name of the strip as the key, and the strip as the value, since we're mostly interested in the keys */ + BLI_ghash_insert(gh, tstrip->name, tstrip); + } + } + + /* if the hash-table has a match for this name, try other names... + * - in an extreme case, it might not be able to find a name, but then everything else in Blender would fail too :) + */ + if (BLI_ghash_haskey(gh, strip->name)) { + char tempname[128]; + int number = 1; + char *dot; + + /* Strip off the suffix */ + dot = strchr(strip->name, '.'); + if (dot) *dot=0; + + /* Try different possibilities */ + for (number = 1; number <= 999; number++) { + /* assemble alternative name */ + BLI_snprintf(tempname, 128, "%s%c%03d", strip->name, ".", number); + + /* if hash doesn't have this, set it */ + if (BLI_ghash_haskey(gh, tempname) == 0) { + BLI_strncpy(strip->name, tempname, sizeof(strip->name)); + break; + } + } + } + + /* free the hash... */ + BLI_ghash_free(gh, NULL, NULL); +} + + +/* Core Tools ------------------------------------------- */ /* For the given AnimData block, add the active action to the NLA * stack (i.e. 'push-down' action). The UI should only allow this diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c index c0a2b9476e3..a74037d1ace 100644 --- a/source/blender/editors/space_nla/nla_buttons.c +++ b/source/blender/editors/space_nla/nla_buttons.c @@ -215,7 +215,8 @@ static void nla_panel_properties(const bContext *C, Panel *pa) /* Strip Properties ------------------------------------- */ /* strip type */ - row= uiLayoutRow(layout, 1); + row= uiLayoutColumn(layout, 1); + uiItemR(row, NULL, ICON_NLA, &strip_ptr, "name", 0, 0, 0); // XXX icon? uiItemR(row, NULL, 0, &strip_ptr, "type", 0, 0, 0); /* strip extents */ diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index 7fb15c62277..8d56670a149 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -445,26 +445,11 @@ static void nla_draw_strip_text (NlaTrack *nlt, NlaStrip *strip, int index, View else sprintf(dir, "->"); - /* for now, just init the string with fixed-formats */ - switch (strip->type) { - case NLASTRIP_TYPE_TRANSITION: /* Transition */ - sprintf(str, "%d | Transition | %.2f %s %.2f", - index, strip->start, dir, strip->end); - break; - - case NLASTRIP_TYPE_META: /* Meta */ - sprintf(str, "%d | %sMeta | %.2f %s %.2f", - index, ((strip->flag & NLASTRIP_FLAG_TEMP_META)?"Temp-":""), - strip->start, dir, strip->end); - break; - - case NLASTRIP_TYPE_CLIP: /* Action-Clip (default) */ - default: - sprintf(str, "%d | Act: %s | %.2f %s %.2f", - index, ((strip->act)?strip->act->id.name+2:""), - strip->start, dir, strip->end); - break; - } + /* just print the name and the range */ + if (strip->flag & NLASTRIP_FLAG_TEMP_META) + sprintf(str, "Temp-Meta | %.2f %s %.2f", strip->start, dir, strip->end); + else + sprintf(str, "%s | %.2f %s %.2f", strip->name, strip->start, dir, strip->end); /* set text colour - if colours (see above) are light, draw black text, otherwise draw white */ if (strip->flag & (NLASTRIP_FLAG_ACTIVE|NLASTRIP_FLAG_SELECT|NLASTRIP_FLAG_TWEAKUSER)) diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index cb151429dd1..9ddd8daab0d 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -307,6 +307,9 @@ static int nlaedit_add_actionclip_exec (bContext *C, wmOperator *op) nlt= add_nlatrack(adt, NULL); BKE_nlatrack_add_strip(nlt, strip); } + + /* auto-name it */ + BKE_nlastrip_validate_name(adt, strip); } /* free temp data */ @@ -363,6 +366,7 @@ static int nlaedit_add_transition_exec (bContext *C, wmOperator *op) /* for each track, find pairs of strips to add transitions to */ for (ale= anim_data.first; ale; ale= ale->next) { NlaTrack *nlt= (NlaTrack *)ale->data; + AnimData *adt= BKE_animdata_from_id(ale->id); NlaStrip *s1, *s2; /* get initial pair of strips */ @@ -410,6 +414,9 @@ static int nlaedit_add_transition_exec (bContext *C, wmOperator *op) strip->scale= 1.0f; strip->repeat = 1.0f; + /* auto-name it */ + BKE_nlastrip_validate_name(adt, strip); + /* make note of this */ done++; } @@ -470,9 +477,18 @@ static int nlaedit_add_meta_exec (bContext *C, wmOperator *op) /* for each track, find pairs of strips to add transitions to */ for (ale= anim_data.first; ale; ale= ale->next) { NlaTrack *nlt= (NlaTrack *)ale->data; + AnimData *adt= BKE_animdata_from_id(ale->id); + NlaStrip *strip; /* create meta-strips from the continuous chains of selected strips */ BKE_nlastrips_make_metas(&nlt->strips, 0); + + /* name the metas */ + for (strip= nlt->strips.first; strip; strip= strip->next) { + /* auto-name this strip if selected (that means it is a meta) */ + if (strip->flag & NLASTRIP_FLAG_SELECT) + BKE_nlastrip_validate_name(adt, strip); + } } /* free temp data */ @@ -605,6 +621,9 @@ static int nlaedit_duplicate_exec (bContext *C, wmOperator *op) /* deselect the original and the active flag */ strip->flag &= ~(NLASTRIP_FLAG_SELECT|NLASTRIP_FLAG_ACTIVE); + /* auto-name it */ + BKE_nlastrip_validate_name(adt, strip); + done++; } } @@ -728,7 +747,7 @@ void NLA_OT_delete (wmOperatorType *ot) // - variable-length splits? /* split a given Action-Clip strip */ -static void nlaedit_split_strip_actclip (NlaTrack *nlt, NlaStrip *strip) +static void nlaedit_split_strip_actclip (AnimData *adt, NlaTrack *nlt, NlaStrip *strip) { NlaStrip *nstrip; float midframe, midaframe, len; @@ -765,10 +784,13 @@ static void nlaedit_split_strip_actclip (NlaTrack *nlt, NlaStrip *strip) /* clear the active flag from the copy */ nstrip->flag &= ~NLASTRIP_FLAG_ACTIVE; + + /* auto-name the new strip */ + BKE_nlastrip_validate_name(adt, nstrip); } /* split a given Meta strip */ -static void nlaedit_split_strip_meta (NlaTrack *nlt, NlaStrip *strip) +static void nlaedit_split_strip_meta (AnimData *adt, NlaTrack *nlt, NlaStrip *strip) { /* simply ungroup it for now... */ BKE_nlastrips_clear_metastrip(&nlt->strips, strip); @@ -795,6 +817,7 @@ static int nlaedit_split_exec (bContext *C, wmOperator *op) /* for each NLA-Track, split all selected strips into two strips */ for (ale= anim_data.first; ale; ale= ale->next) { NlaTrack *nlt= (NlaTrack *)ale->data; + AnimData *adt= BKE_animdata_from_id(ale->id); NlaStrip *strip, *next; for (strip= nlt->strips.first; strip; strip= next) { @@ -805,11 +828,11 @@ static int nlaedit_split_exec (bContext *C, wmOperator *op) /* splitting method depends on the type of strip */ switch (strip->type) { case NLASTRIP_TYPE_CLIP: /* action-clip */ - nlaedit_split_strip_actclip(nlt, strip); + nlaedit_split_strip_actclip(adt, nlt, strip); break; case NLASTRIP_TYPE_META: /* meta-strips need special handling */ - nlaedit_split_strip_meta(nlt, strip); + nlaedit_split_strip_meta(adt, nlt, strip); break; default: /* for things like Transitions, do not split! */ diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h index d71beb8785b..fed0c490014 100644 --- a/source/blender/makesdna/DNA_anim_types.h +++ b/source/blender/makesdna/DNA_anim_types.h @@ -445,6 +445,8 @@ typedef struct NlaStrip { ListBase fcurves; /* F-Curves for controlling this strip's influence and timing */ // TODO: move out? ListBase modifiers; /* F-Curve modifiers to be applied to the entire strip's referenced F-Curves */ + char name[64]; /* User-Visible Identifier for Strip */ + float influence; /* Influence of strip */ float strip_time; /* Current 'time' within action being used (automatically evaluated, but can be overridden) */ diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c index 97f35af1db7..bc636af6849 100644 --- a/source/blender/makesrna/intern/rna_nla.c +++ b/source/blender/makesrna/intern/rna_nla.c @@ -41,11 +41,27 @@ #include /* needed for some of the validation stuff... */ +#include "BKE_animsys.h" #include "BKE_nla.h" /* temp constant defined for these funcs only... */ #define NLASTRIP_MIN_LEN_THRESH 0.1f +void rna_NlaStrip_name_set(PointerRNA *ptr, const char *value) +{ + NlaStrip *data= (NlaStrip *)ptr->data; + + /* copy the name first */ + BLI_strncpy(data->name, value, sizeof(data->name)); + + /* validate if there's enough info to do so */ + if (ptr->id.data) { + AnimData *adt= BKE_animdata_from_id(ptr->id.data); + BKE_nlastrip_validate_name(adt, data); + } +} + + static void rna_NlaStrip_start_frame_set(PointerRNA *ptr, float value) { NlaStrip *data= (NlaStrip*)ptr->data; @@ -255,6 +271,12 @@ void rna_def_nlastrip(BlenderRNA *brna) RNA_def_struct_ui_text(srna, "NLA Strip", "A container referencing an existing Action."); RNA_def_struct_ui_icon(srna, ICON_NLA); // XXX + /* name property */ + prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); + RNA_def_property_ui_text(prop, "Name", ""); + RNA_def_property_string_funcs(prop, NULL, NULL, "rna_NlaStrip_name_set"); + RNA_def_struct_name_property(srna, prop); + /* Enums */ prop= RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "type"); From 1105ee701ed20d6301a174fc4285de00f8e0f95e Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sat, 11 Jul 2009 03:09:44 +0000 Subject: [PATCH 114/114] NLA SoC: Quick commit of skeleton of auto-blending setting code to be completed later... --- source/blender/blenkernel/intern/nla.c | 56 ++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index a240de209d9..457df9be7a9 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -1227,6 +1227,62 @@ void BKE_nlastrip_validate_name (AnimData *adt, NlaStrip *strip) BLI_ghash_free(gh, NULL, NULL); } +/* ---- */ + +/* Determine auto-blending for the given strip */ +void BKE_nlastrip_validate_autoblends (NlaTrack *nlt, NlaStrip *nls) +{ + NlaTrack *track; + NlaStrip *strip; + //float *ps=NULL, *pe=NULL; + //float *ns=NULL, *ne=NULL; + + /* sanity checks */ + if ELEM(NULL, nls, nlt) + return; + if ((nlt->prev == NULL) && (nlt->next == NULL)) + return; + if ((nls->flag & NLASTRIP_FLAG_AUTO_BLENDS)==0) + return; + + /* get test ranges */ + if (nlt->prev) { + /* find strips that overlap over the start/end of the given strip, + * but which don't cover the entire length + */ + track= nlt->prev; + for (strip= track->strips.first; strip; strip= strip->next) { + + } + } + if (nlt->next) { + /* find strips that overlap over the start/end of the given strip, + * but which don't cover the entire length + */ + track= nlt->next; + for (strip= track->strips.first; strip; strip= strip->next) { + + } + } +} + +/* Ensure that auto-blending and other settings are set correctly */ +void BKE_nla_validate_state (AnimData *adt) +{ + NlaStrip *strip; + NlaTrack *nlt; + + /* sanity checks */ + if ELEM(NULL, adt, adt->nla_tracks.first) + return; + + /* adjust blending values for auto-blending */ + for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) { + for (strip= nlt->strips.first; strip; strip= strip->next) { + BKE_nlastrip_validate_autoblends(nlt, strip); + } + } +} /* Core Tools ------------------------------------------- */