Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors')
-rw-r--r--source/blender/editors/animation/anim_channels.c52
-rw-r--r--source/blender/editors/animation/anim_filter.c592
-rw-r--r--source/blender/editors/animation/keyframes_draw.c2
-rw-r--r--source/blender/editors/include/ED_anim_api.h42
-rw-r--r--source/blender/editors/include/ED_object.h17
-rw-r--r--source/blender/editors/include/UI_interface.h9
-rw-r--r--source/blender/editors/include/UI_view2d.h2
-rw-r--r--source/blender/editors/interface/interface.c13
-rw-r--r--source/blender/editors/interface/interface_api.c11
-rw-r--r--source/blender/editors/interface/interface_handlers.c6
-rw-r--r--source/blender/editors/interface/interface_utils.c4
-rw-r--r--source/blender/editors/interface/interface_widgets.c6
-rw-r--r--source/blender/editors/interface/resources.c19
-rw-r--r--source/blender/editors/interface/view2d.c23
-rw-r--r--source/blender/editors/object/editconstraint.c293
-rw-r--r--source/blender/editors/object/object_intern.h3
-rw-r--r--source/blender/editors/object/object_modifier.c2
-rw-r--r--source/blender/editors/object/object_ops.c2
-rw-r--r--source/blender/editors/space_action/action_select.c3
-rw-r--r--source/blender/editors/space_file/filesel.c3
-rw-r--r--source/blender/editors/space_graph/space_graph.c2
-rw-r--r--source/blender/editors/space_image/image_header.c14
-rw-r--r--source/blender/editors/space_nla/nla_channels.c444
-rw-r--r--source/blender/editors/space_nla/nla_draw.c626
-rw-r--r--source/blender/editors/space_nla/nla_edit.c74
-rw-r--r--source/blender/editors/space_nla/nla_header.c76
-rw-r--r--source/blender/editors/space_nla/nla_intern.h57
-rw-r--r--source/blender/editors/space_nla/nla_ops.c158
-rw-r--r--source/blender/editors/space_nla/nla_select.c440
-rw-r--r--source/blender/editors/space_nla/space_nla.c207
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c1
-rw-r--r--source/blender/editors/space_view3d/view3d_header.c24
32 files changed, 2591 insertions, 636 deletions
diff --git a/source/blender/editors/animation/anim_channels.c b/source/blender/editors/animation/anim_channels.c
index 9e0e50a8de5..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 */
@@ -149,6 +123,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 +148,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;
}
}
@@ -217,6 +205,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 +255,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/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index afad396607b..ed526bd99a0 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), "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) */
+ 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,42 @@ 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_NLA_NOACT) && ANIMDATA_HAS_KEYS(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 +557,25 @@ 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;
+ case ANIMTYPE_NLAACTION:
+ {
+ /* nothing to include for now... nothing editable from NLA-perspective here */
+ ale->key_data= NULL;
+ ale->datatype= ALE_NONE;
+ }
+ break;
}
}
@@ -522,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) {
@@ -610,6 +691,55 @@ static int animdata_filter_action (ListBase *anim_data, bAction *act, int filter
return items;
}
+static int animdata_filter_nla (ListBase *anim_data, AnimData *adt, int filter_mode, void *owner, short ownertype, ID *owner_id)
+{
+ 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 (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);
+ 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)
{
bAnimListElem *ale;
@@ -752,19 +882,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 +930,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, 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 +996,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, 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 +1010,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 +1032,81 @@ 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++;
+ }
}
- }
-
- /* 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++;
+#endif
+
+ /* add NLA tracks */
+ items += animdata_filter_nla(anim_data, adt, 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 (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 */
+ items += animdata_filter_nla(anim_data, adt, 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 +1116,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 +1150,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 +1162,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 +1174,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 +1192,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 +1212,80 @@ 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++;
+ }
}
- }
-
- /* 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++;
+#endif
+
+ /* add NLA tracks */
+ items += animdata_filter_nla(anim_data, adt, 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 (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 */
+ items += animdata_filter_nla(anim_data, adt, 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 +1299,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 */
@@ -1182,22 +1338,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) */
@@ -1239,13 +1391,19 @@ 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 */
+ actOk= 0;
+ keyOk= 0;
+ 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 */
@@ -1260,18 +1418,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;
}
}
@@ -1280,19 +1433,21 @@ 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));
+ dataOk= 0;
+ 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));
+ dataOk= 0;
+ 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 --- */
@@ -1400,6 +1555,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 efc0a0b9a57..cdd8b5c368c 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,9 @@ typedef enum eAnim_ChannelType {
ANIMTYPE_GPDATABLOCK,
ANIMTYPE_GPLAYER,
+
+ ANIMTYPE_NLATRACK,
+ ANIMTYPE_NLAACTION,
} eAnim_ChannelType;
/* types of keyframe data in bAnimListElem */
@@ -135,6 +139,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 +207,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 */
@@ -308,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/include/ED_object.h b/source/blender/editors/include/ED_object.h
index 3d0de795778..c6277f319bc 100644
--- a/source/blender/editors/include/ED_object.h
+++ b/source/blender/editors/include/ED_object.h
@@ -35,7 +35,6 @@ struct bContext;
struct Base;
struct View3D;
struct bConstraint;
-struct bConstraintChannel;
struct KeyBlock;
struct Lattice;
struct Mesh;
@@ -72,20 +71,8 @@ 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 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);
+struct bConstraint *add_new_constraint (short type);
+void add_constraint_to_object (struct bConstraint *con, struct Object *ob);
/* 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 97c2da5297f..cdb29ecf376 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -189,8 +189,6 @@ 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
@@ -581,8 +579,7 @@ 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 PointerRNA *ptr);
-uiLayout *uiTemplateConstraint(uiLayout *layout, struct PointerRNA *ptr);
+uiLayout *uiTemplateModifier(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr);
void uiTemplatePreview(uiLayout *layout, struct ID *id);
/* items */
@@ -595,8 +592,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, 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 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 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/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h
index 4813b695795..50283113b62 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/interface.c b/source/blender/editors/interface/interface.c
index e9a886375c3..0b094f0c8dc 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(ELEM3(but->type, TOGN, ICONTOGN, OPTIONN)) true= 0;
+ if( but->type==TOGN || but->type==ICONTOGN) true= 0;
if( but->bit ) {
lvalue= (int)value;
@@ -700,12 +700,10 @@ 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:
@@ -1511,12 +1509,7 @@ 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(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)) {
+ if(prop && RNA_property_collection_lookup_string(&ptr, prop, str, &rptr)) {
RNA_property_pointer_set(&but->rnapoin, but->rnaprop, rptr);
return 1;
}
@@ -1996,7 +1989,7 @@ void uiBlockEndAlign(uiBlock *block)
int ui_but_can_align(uiBut *but)
{
- return !ELEM3(but->type, LABEL, OPTION, OPTIONN);
+ return (but->type != LABEL);
}
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 2bbaee857d1..3cb6678133f 100644
--- a/source/blender/editors/interface/interface_api.c
+++ b/source/blender/editors/interface/interface_api.c
@@ -89,8 +89,7 @@ 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 widget for numeric values.");
- RNA_def_boolean(func, "toggle", 0, "", "Use toggle widget for boolean values.");
+ RNA_def_boolean(func, "slider", 0, "", "Use slider for numeric values.");
func= RNA_def_function(srna, "items_enumR", "uiItemsEnumR");
parm= RNA_def_pointer(func, "data", "AnyType", "", "Data from which to take property.");
@@ -199,13 +198,9 @@ 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, "data", "AnyType", "", "Modifier data.");
+ parm= RNA_def_pointer(func, "context", "Context", "", "Current context.");
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.");
+ 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);
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index ec2f960dd14..ce01bc19856 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(ELEM3(but->type, TOGN, ICONTOGN, OPTIONN)) push= !push;
+ if(but->type==TOGN || but->type==ICONTOGN) push= !push;
ui_set_but_val(but, (double)push);
if(but->type==ICONTOG || but->type==ICONTOGN) ui_check_but(but);
}
@@ -566,8 +566,6 @@ 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:
@@ -2674,8 +2672,6 @@ 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 7c739adf1b9..16451ec4510 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, OPTION, 0, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
+ but= uiDefButR(block, TOG, 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, 0);
+ uiItemFullR(uiLayoutColumn(split, 0), "", 0, ptr, prop, -1, 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 f4e3a7f2899..f779022ece5 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -1830,13 +1830,11 @@ 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/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 b363f1f6272..19c95ce7ce0 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/object/editconstraint.c b/source/blender/editors/object/editconstraint.c
index b2cf3be6229..d0e487f98c7 100644
--- a/source/blender/editors/object/editconstraint.c
+++ b/source/blender/editors/object/editconstraint.c
@@ -49,27 +49,17 @@
#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"
@@ -599,6 +589,55 @@ 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,
@@ -850,237 +889,3 @@ 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 ce8bd7287f7..223f2190f4b 100644
--- a/source/blender/editors/object/object_intern.h
+++ b/source/blender/editors/object/object_intern.h
@@ -88,8 +88,5 @@ 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 2e2c16ee6d6..339d8bc8252 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -368,8 +368,6 @@ 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 9d8247522e1..f2a020e69a6 100644
--- a/source/blender/editors/object/object_ops.c
+++ b/source/blender/editors/object/object_ops.c
@@ -101,8 +101,6 @@ 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_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_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_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_image/image_header.c b/source/blender/editors/space_image/image_header.c
index 9a61d3a7081..2accef990d3 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, 0);
- // XXX if(show_uvedit) uiItemR(layout, NULL, 0, &uvptr, "local_view", 0, 0, 0); // "UV Local View", Numpad /
+ 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 /
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, 0);
+ uiItemR(layout, NULL, 0, &spaceptr, "image_painting", 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, 0);
- uiItemR(layout, NULL, 0, &uvptr, "constrain_to_image_bounds", 0, 0, 0);
+ uiItemR(layout, NULL, 0, &uvptr, "snap_to_pixels", 0, 0);
+ uiItemR(layout, NULL, 0, &uvptr, "constrain_to_image_bounds", 0, 0);
uiItemS(layout);
- uiItemR(layout, NULL, 0, &uvptr, "live_unwrap", 0, 0, 0);
+ uiItemR(layout, NULL, 0, &uvptr, "live_unwrap", 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, 0);
+ uiItemR(layout, NULL, 0, &sceneptr, "proportional_editing", 0, 0);
uiItemMenuEnumR(layout, NULL, 0, &sceneptr, "proportional_editing_falloff");
uiItemS(layout);
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..a839ccbf3d6
--- /dev/null
+++ b/source/blender/editors/space_nla/nla_channels.c
@@ -0,0 +1,444 @@
+/**
+ * $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 <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#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 */
+
+/* ******************** 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
+ * 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
new file mode 100644
index 00000000000..def49021160
--- /dev/null
+++ b/source/blender/editors/space_nla/nla_draw.c
@@ -0,0 +1,626 @@
+/**
+ * $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 <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#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);
+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, 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_shade(GL_POLYGON, strip->start, yminc, strip->end, ymaxc, 0.0, 0.5, 0.1);
+
+ /* 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_shade(GL_LINE_LOOP, strip->start, yminc, strip->end, ymaxc, 0.0, 0.0, 0.1);
+}
+
+/* ---------------------- */
+
+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 (if visible) */
+ for (strip=nlt->strips.first; strip; strip= strip->next) {
+ if (BKE_nlastrip_within_bounds(strip, v2d->cur.xmin, v2d->cur.xmax))
+ 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 */
+
+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;
+
+ sel = SEL_NLT(nlt);
+ 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, "<No Action>");
+ }
+ 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, 10);
+ }
+ 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((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... */
+ 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' - 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_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);
+ }
+
+ 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..ce9ae7de7a9
--- /dev/null
+++ b/source/blender/editors/space_nla/nla_edit.c
@@ -0,0 +1,74 @@
+/**
+ * $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 <string.h>
+#include <stdio.h>
+
+#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_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
+
+/* *********************************************** */
+
+/* *********************************************** */
+
+/* *********************************************** */
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 <string.h>
#include <stdio.h>
+#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..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 *****
*/
@@ -30,10 +30,63 @@
/* 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_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar);
+void draw_nla_channel_list(bAnimContext *ac, SpaceNla *snla, ARegion *ar);
+
+/* **************************************** */
/* nla_header.c */
+
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 */
+
+/* **************************************** */
+/* nla_channels.c */
+
+void NLA_OT_channels_select_border(wmOperatorType *ot);
+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
new file mode 100644
index 00000000000..167686c99f9
--- /dev/null
+++ b/source/blender/editors/space_nla/nla_ops.c
@@ -0,0 +1,158 @@
+/**
+ * $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 <string.h>
+#include <stdio.h>
+
+#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 "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "nla_intern.h" // own include
+
+
+/* ************************** registration - operator types **********************************/
+
+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 **********************************/
+
+static void nla_keymap_channels (wmWindowManager *wm, ListBase *keymap)
+{
+ /* 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);
+
+ /* 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);
+
+ /* 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)
+{
+ 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 */
+ //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/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 <string.h>
+#include <stdio.h>
+
+#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 6e1a97dea34..024b23c51b8 100644
--- a/source/blender/editors/space_nla/space_nla.c
+++ b/source/blender/editors/space_nla/space_nla.c
@@ -29,6 +29,7 @@
#include <string.h>
#include <stdio.h>
+#include "DNA_anim_types.h"
#include "DNA_nla_types.h"
#include "DNA_object_types.h"
#include "DNA_space_types.h"
@@ -41,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"
@@ -57,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 ***************** */
@@ -71,6 +76,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");
@@ -78,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");
@@ -95,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;
@@ -111,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;
}
@@ -122,15 +133,25 @@ 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);
+ }
}
/* 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)
@@ -138,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, "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 */
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 */
@@ -154,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);
}
@@ -174,16 +216,20 @@ 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);
}
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);
@@ -191,25 +237,40 @@ 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_nla_main_data(&ac, snla, 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)
-{
-
-}
-
-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)
@@ -242,6 +303,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 */
@@ -257,6 +394,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 */
@@ -265,7 +403,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);
@@ -286,8 +424,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/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 70f90a1a9d9..3b3fd5109cf 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -393,7 +393,6 @@ static void view3d_main_area_listener(ARegion *ar, wmNotifier *wmn)
case ND_GEOM_DATA:
case ND_DRAW:
case ND_MODIFIER:
- case ND_CONSTRAINT:
case ND_KEYS:
ED_region_tag_redraw(ar);
break;
diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c
index 2d623c9c33d..5b8de93b542 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, 0); // |O
+ uiItemR(layout, NULL, 0, &sceneptr, "proportional_editing", 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, 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);
+ 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);
/* 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, 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, "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, "flip_direction", 0, 0, 0);
+ uiItemR(layout, NULL, 0, &rna, "flip_direction", 0, 0);
}
uiBlock *view3d_sculptmenu(bContext *C, ARegion *ar, void *arg_unused)