2.5 - NLA SoC Branch Merged to 2.5!
(19863 to 21513) Highlights of the new NLA System (and related Animation System changes): * NLA Data is stored in AnimData alongside Action and Drivers. The NLA stack is evaluated before the Action, with the Action always overriding the results of the stack. * NLA Data is arranged in 'Tracks', which act like PhotoShop layers. These can be muted, protected, and/or made to be played back by themselves * Within each track, there can be multiple 'Strips'. There are 3 types of strip -> Action Clip (references some action), Transition (blends between the endpoints of two strips), and Meta (container for several strips that occur sequentially) * FModifiers can be applied to strips, and strips can have animated influence/time controls. Playback for strips can also be backwards now! * Playback can now go in forward and backwards directions. * Animation Editors have been polished (unfinished features added, existing features cleaned up and made more consistent) Notes for BuildSystem Maintainers: * Only scons has been actively tested. Makefiles should work fine. * MSVC ProjectFiles are broken due to the very way they work. * CMake status unknown... Other notes: * Hopefully I haven't made any mistakes while doing the merge. More files than expected were showing some weird conflicts, so you may have some broken code... * Not all old files (with NLA) data load exactly the same anymore. However, the bulk of the files out there should be ok (I hope)
This commit is contained in:
@@ -68,6 +68,9 @@ void make_local_action(struct bAction *act);
|
||||
/* Some kind of bounding box operation on the action */
|
||||
void calc_action_range(const struct bAction *act, float *start, float *end, int incl_hidden);
|
||||
|
||||
/* Does action have any motion data at all? */
|
||||
short action_has_motion(const struct bAction *act);
|
||||
|
||||
/* Action Groups API ----------------- */
|
||||
|
||||
/* Make the given Action Group the active one */
|
||||
@@ -145,12 +148,6 @@ void copy_pose_result(struct bPose *to, struct bPose *from);
|
||||
/* clear all transforms */
|
||||
void rest_pose(struct bPose *pose);
|
||||
|
||||
/* map global time (frame nr) to strip converted time, doesn't clip */
|
||||
float get_action_frame(struct Object *ob, float cframe);
|
||||
/* map strip time to global time (frame nr) */
|
||||
float get_action_frame_inv(struct Object *ob, float cframe);
|
||||
|
||||
|
||||
/* functions used by the game engine */
|
||||
void game_copy_pose(struct bPose **dst, struct bPose *src);
|
||||
void game_free_pose(struct bPose *pose);
|
||||
|
||||
@@ -1,12 +1,33 @@
|
||||
/* Testing code for new animation system in 2.5
|
||||
* Copyright 2009, Joshua Leung
|
||||
/**
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
|
||||
* All rights reserved.
|
||||
*
|
||||
* Contributor(s): Joshua Leung (full recode)
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#ifndef BKE_FCURVE_H
|
||||
#define BKE_FCURVE_H
|
||||
|
||||
//struct ListBase;
|
||||
|
||||
struct FCurve;
|
||||
struct FModifier;
|
||||
struct ChannelDriver;
|
||||
@@ -54,8 +75,8 @@ typedef struct FModifierTypeInfo {
|
||||
short size; /* size in bytes of the struct */
|
||||
short acttype; /* eFMI_Action_Types */
|
||||
short requires; /* eFMI_Requirement_Flags */
|
||||
char name[32]; /* name of modifier in interface */
|
||||
char structName[32]; /* name of struct for SDNA */
|
||||
char name[64]; /* name of modifier in interface */
|
||||
char structName[64]; /* name of struct for SDNA */
|
||||
|
||||
/* data management function pointers - special handling */
|
||||
/* free any data that is allocated separately (optional) */
|
||||
@@ -104,14 +125,20 @@ FModifierTypeInfo *get_fmodifier_typeinfo(int type);
|
||||
|
||||
/* ---------------------- */
|
||||
|
||||
struct FModifier *fcurve_add_modifier(struct FCurve *fcu, int type);
|
||||
void fcurve_copy_modifiers(ListBase *dst, ListBase *src);
|
||||
void fcurve_remove_modifier(struct FCurve *fcu, struct FModifier *fcm);
|
||||
void fcurve_free_modifiers(struct FCurve *fcu);
|
||||
void fcurve_bake_modifiers(struct FCurve *fcu, int start, int end);
|
||||
struct FModifier *add_fmodifier(ListBase *modifiers, int type);
|
||||
void copy_fmodifiers(ListBase *dst, ListBase *src);
|
||||
void remove_fmodifier(ListBase *modifiers, struct FModifier *fcm);
|
||||
void free_fmodifiers(ListBase *modifiers);
|
||||
|
||||
struct FModifier *fcurve_find_active_modifier(struct FCurve *fcu);
|
||||
void fcurve_set_active_modifier(struct FCurve *fcu, struct FModifier *fcm);
|
||||
struct FModifier *find_active_fmodifier(ListBase *modifiers);
|
||||
void set_active_fmodifier(ListBase *modifiers, struct FModifier *fcm);
|
||||
|
||||
short list_has_suitable_fmodifier(ListBase *modifiers, int mtype, short acttype);
|
||||
|
||||
float evaluate_time_fmodifiers(ListBase *modifiers, struct FCurve *fcu, float cvalue, float evaltime);
|
||||
void evaluate_value_fmodifiers(ListBase *modifiers, struct FCurve *fcu, float *cvalue, float evaltime);
|
||||
|
||||
void fcurve_bake_modifiers(struct FCurve *fcu, int start, int end);
|
||||
|
||||
/* ************** F-Curves API ******************** */
|
||||
|
||||
@@ -126,9 +153,6 @@ void copy_fcurves(ListBase *dst, ListBase *src);
|
||||
/* find matching F-Curve in the given list of F-Curves */
|
||||
struct FCurve *list_find_fcurve(ListBase *list, const char rna_path[], const int array_index);
|
||||
|
||||
/* test if there is a keyframe at cfra */
|
||||
short on_keyframe_fcurve(struct FCurve *fcu, float cfra);
|
||||
|
||||
/* get the time extents for F-Curve */
|
||||
void calc_fcurve_range(struct FCurve *fcu, float *min, float *max);
|
||||
|
||||
|
||||
@@ -17,12 +17,12 @@
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
* The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
* Contributor(s): Joshua Leung (full recode)
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
@@ -30,15 +30,90 @@
|
||||
#ifndef BKE_NLA_H
|
||||
#define BKE_NLA_H
|
||||
|
||||
struct bActionStrip;
|
||||
struct ListBase;
|
||||
struct Object;
|
||||
struct AnimData;
|
||||
struct NlaStrip;
|
||||
struct NlaTrack;
|
||||
struct bAction;
|
||||
|
||||
/* ----------------------------- */
|
||||
/* Data Management */
|
||||
|
||||
void free_nlastrip(ListBase *strips, struct NlaStrip *strip);
|
||||
void free_nlatrack(ListBase *tracks, struct NlaTrack *nlt);
|
||||
void free_nladata(ListBase *tracks);
|
||||
|
||||
struct NlaStrip *copy_nlastrip(struct NlaStrip *strip);
|
||||
struct NlaTrack *copy_nlatrack(struct NlaTrack *nlt);
|
||||
void copy_nladata(ListBase *dst, ListBase *src);
|
||||
|
||||
struct NlaTrack *add_nlatrack(struct AnimData *adt, struct NlaTrack *prev);
|
||||
struct NlaStrip *add_nlastrip(struct bAction *act);
|
||||
struct NlaStrip *add_nlastrip_to_stack(struct AnimData *adt, struct bAction *act);
|
||||
|
||||
/* ----------------------------- */
|
||||
/* API */
|
||||
|
||||
short BKE_nlastrips_has_space(ListBase *strips, float start, float end);
|
||||
void BKE_nlastrips_sort_strips(ListBase *strips);
|
||||
|
||||
short BKE_nlastrips_add_strip(ListBase *strips, struct NlaStrip *strip);
|
||||
|
||||
|
||||
void BKE_nlastrips_make_metas(ListBase *strips, short temp);
|
||||
void BKE_nlastrips_clear_metas(ListBase *strips, short onlySel, short onlyTemp);
|
||||
void BKE_nlastrips_clear_metastrip(ListBase *strips, struct NlaStrip *strip);
|
||||
short BKE_nlameta_add_strip(struct NlaStrip *mstrip, struct NlaStrip *strip);
|
||||
void BKE_nlameta_flush_transforms(struct NlaStrip *mstrip);
|
||||
|
||||
/* ............ */
|
||||
|
||||
struct NlaTrack *BKE_nlatrack_find_active(ListBase *tracks);
|
||||
void BKE_nlatrack_set_active(ListBase *tracks, struct NlaTrack *nlt);
|
||||
|
||||
void BKE_nlatrack_solo_toggle(struct AnimData *adt, struct NlaTrack *nlt);
|
||||
|
||||
short BKE_nlatrack_has_space(struct NlaTrack *nlt, float start, float end);
|
||||
void BKE_nlatrack_sort_strips(struct NlaTrack *nlt);
|
||||
|
||||
short BKE_nlatrack_add_strip(struct NlaTrack *nlt, struct NlaStrip *strip);
|
||||
|
||||
/* ............ */
|
||||
|
||||
struct NlaStrip *BKE_nlastrip_find_active(struct NlaTrack *nlt);
|
||||
|
||||
short BKE_nlastrip_within_bounds(struct NlaStrip *strip, float min, float max);
|
||||
|
||||
void BKE_nlastrip_validate_name(struct AnimData *adt, struct NlaStrip *strip);
|
||||
|
||||
/* ............ */
|
||||
|
||||
short BKE_nlatrack_has_animated_strips(struct NlaTrack *nlt);
|
||||
short BKE_nlatracks_have_animated_strips(ListBase *tracks);
|
||||
void BKE_nlastrip_validate_fcurves(struct NlaStrip *strip);
|
||||
|
||||
/* ............ */
|
||||
|
||||
void BKE_nla_action_pushdown(struct AnimData *adt);
|
||||
|
||||
short BKE_nla_tweakmode_enter(struct AnimData *adt);
|
||||
void BKE_nla_tweakmode_exit(struct AnimData *adt);
|
||||
|
||||
/* ----------------------------- */
|
||||
/* Time Mapping */
|
||||
|
||||
/* time mapping conversion modes */
|
||||
enum {
|
||||
/* convert from global time to strip time - for evaluation */
|
||||
NLATIME_CONVERT_EVAL = 0,
|
||||
/* convert from global time to strip time - for editing corrections */
|
||||
// XXX old 0 invert
|
||||
NLATIME_CONVERT_UNMAP,
|
||||
/* convert from strip time to global time */
|
||||
// xxx old 1 invert
|
||||
NLATIME_CONVERT_MAP,
|
||||
} eNlaTime_ConvertModes;
|
||||
|
||||
float BKE_nla_tweakedit_remap(struct AnimData *adt, float cframe, short mode);
|
||||
|
||||
void free_actionstrip (struct bActionStrip* strip);
|
||||
void free_nlastrips (struct ListBase *nlalist);
|
||||
void copy_nlastrips (struct ListBase *dst, struct ListBase *src);
|
||||
void copy_actionstrip (struct bActionStrip **dst, struct bActionStrip **src);
|
||||
void find_stridechannel(struct Object *ob, struct bActionStrip *strip);
|
||||
struct bActionStrip *convert_action_to_strip (struct Object *ob);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -128,6 +128,7 @@
|
||||
|
||||
#define IS_EQT(a, b, c) ((a > b)? (((a-b) <= c)? 1:0) : ((((b-a) <= c)? 1:0)))
|
||||
#define IN_RANGE(a, b, c) ((b < c)? ((b<a && a<c)? 1:0) : ((c<a && a<b)? 1:0))
|
||||
#define IN_RANGE_INCL(a, b, c) ((b < c)? ((b<=a && a<=c)? 1:0) : ((c<=a && a<=b)? 1:0))
|
||||
|
||||
/* this weirdo pops up in two places ... */
|
||||
#if !defined(WIN32)
|
||||
|
||||
@@ -769,70 +769,23 @@ void framechange_poses_clear_unkeyed(void)
|
||||
|
||||
/* ************** time ****************** */
|
||||
|
||||
static bActionStrip *get_active_strip(Object *ob)
|
||||
/* Check if the given action has any keyframes */
|
||||
short action_has_motion(const bAction *act)
|
||||
{
|
||||
#if 0 // XXX old animation system
|
||||
bActionStrip *strip;
|
||||
FCurve *fcu;
|
||||
|
||||
if(ob->action==NULL)
|
||||
return NULL;
|
||||
|
||||
for (strip=ob->nlastrips.first; strip; strip=strip->next)
|
||||
if(strip->flag & ACTSTRIP_ACTIVE)
|
||||
break;
|
||||
/* return on the first F-Curve that has some keyframes/samples defined */
|
||||
if (act) {
|
||||
for (fcu= act->curves.first; fcu; fcu= fcu->next) {
|
||||
if (fcu->totvert)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(strip && strip->act==ob->action)
|
||||
return strip;
|
||||
#endif // XXX old animation system
|
||||
|
||||
return NULL;
|
||||
/* nothing found */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* non clipped mapping of strip */
|
||||
static float get_actionstrip_frame(bActionStrip *strip, float cframe, int invert)
|
||||
{
|
||||
float length, actlength, repeat, scale;
|
||||
|
||||
if (strip->repeat == 0.0f) strip->repeat = 1.0f;
|
||||
repeat = (strip->flag & ACTSTRIP_USESTRIDE) ? (1.0f) : (strip->repeat);
|
||||
|
||||
if (strip->scale == 0.0f) strip->scale= 1.0f;
|
||||
scale = (float)fabs(strip->scale); /* scale must be positive (for now) */
|
||||
|
||||
actlength = strip->actend-strip->actstart;
|
||||
if (actlength == 0.0f) actlength = 1.0f;
|
||||
length = repeat * scale * actlength;
|
||||
|
||||
/* invert = convert action-strip time to global time */
|
||||
if (invert)
|
||||
return length*(cframe - strip->actstart)/(repeat*actlength) + strip->start;
|
||||
else
|
||||
return repeat*actlength*(cframe - strip->start)/length + strip->actstart;
|
||||
}
|
||||
|
||||
/* if the conditions match, it converts current time to strip time */
|
||||
float get_action_frame(Object *ob, float cframe)
|
||||
{
|
||||
bActionStrip *strip= get_active_strip(ob);
|
||||
|
||||
if(strip)
|
||||
return get_actionstrip_frame(strip, cframe, 0);
|
||||
return cframe;
|
||||
}
|
||||
|
||||
/* inverted, strip time to current time */
|
||||
float get_action_frame_inv(Object *ob, float cframe)
|
||||
{
|
||||
bActionStrip *strip= get_active_strip(ob);
|
||||
|
||||
if(strip)
|
||||
return get_actionstrip_frame(strip, cframe, 1);
|
||||
return cframe;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Calculate the extents of given action */
|
||||
void calc_action_range(const bAction *act, float *start, float *end, int incl_hidden)
|
||||
{
|
||||
|
||||
@@ -1,10 +1,37 @@
|
||||
/* Testing code for new animation system in 2.5
|
||||
* Copyright 2009, Joshua Leung
|
||||
/**
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): Joshua Leung (full recode)
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
@@ -12,9 +39,12 @@
|
||||
#include "BLI_arithb.h"
|
||||
#include "BLI_dynstr.h"
|
||||
|
||||
#include "DNA_anim_types.h"
|
||||
|
||||
#include "BKE_animsys.h"
|
||||
#include "BKE_action.h"
|
||||
#include "BKE_fcurve.h"
|
||||
#include "BKE_nla.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_utildefines.h"
|
||||
@@ -22,7 +52,7 @@
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_types.h"
|
||||
|
||||
#include "DNA_anim_types.h"
|
||||
#include "nla_private.h"
|
||||
|
||||
/* ***************************************** */
|
||||
/* AnimData API */
|
||||
@@ -116,7 +146,13 @@ void BKE_free_animdata (ID *id)
|
||||
/* unlink action (don't free, as it's in its own list) */
|
||||
if (adt->action)
|
||||
adt->action->id.us--;
|
||||
/* same goes for the temporarily displaced action */
|
||||
if (adt->tmpact)
|
||||
adt->tmpact->id.us--;
|
||||
|
||||
/* free nla data */
|
||||
free_nladata(&adt->nla_tracks);
|
||||
|
||||
/* free drivers - stored as a list of F-Curves */
|
||||
free_fcurves(&adt->drivers);
|
||||
|
||||
@@ -146,9 +182,10 @@ AnimData *BKE_copy_animdata (AnimData *adt)
|
||||
// XXX review this... it might not be optimal behaviour yet...
|
||||
//id_us_plus((ID *)dadt->action);
|
||||
dadt->action= copy_action(adt->action);
|
||||
dadt->tmpact= copy_action(adt->tmpact);
|
||||
|
||||
/* duplicate NLA data */
|
||||
// XXX todo...
|
||||
copy_nladata(&dadt->nla_tracks, &adt->nla_tracks);
|
||||
|
||||
/* duplicate drivers (F-Curves) */
|
||||
copy_fcurves(&dadt->drivers, &adt->drivers);
|
||||
@@ -355,10 +392,10 @@ void BKE_keyingsets_free (ListBase *list)
|
||||
short animsys_remap_path (AnimMapper *remap, char *path, char **dst)
|
||||
{
|
||||
/* is there a valid remapping table to use? */
|
||||
if (remap) {
|
||||
//if (remap) {
|
||||
/* find a matching entry... to use to remap */
|
||||
// ...TODO...
|
||||
}
|
||||
//}
|
||||
|
||||
/* nothing suitable found, so just set dst to look at path (i.e. no alloc/free needed) */
|
||||
*dst= path;
|
||||
@@ -455,11 +492,14 @@ static void animsys_evaluate_fcurves (PointerRNA *ptr, ListBase *list, AnimMappe
|
||||
/* calculate then execute each curve */
|
||||
for (fcu= list->first; fcu; fcu= fcu->next)
|
||||
{
|
||||
/* check if this curve should be skipped */
|
||||
if ((fcu->flag & (FCURVE_MUTED|FCURVE_DISABLED)) == 0)
|
||||
{
|
||||
calculate_fcurve(fcu, ctime);
|
||||
animsys_execute_fcurve(ptr, remap, fcu);
|
||||
/* check if this F-Curve doesn't belong to a muted group */
|
||||
if ((fcu->grp == NULL) || (fcu->grp->flag & AGRP_MUTED)==0) {
|
||||
/* check if this curve should be skipped */
|
||||
if ((fcu->flag & (FCURVE_MUTED|FCURVE_DISABLED)) == 0)
|
||||
{
|
||||
calculate_fcurve(fcu, ctime);
|
||||
animsys_execute_fcurve(ptr, remap, fcu);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -481,7 +521,6 @@ static void animsys_evaluate_drivers (PointerRNA *ptr, AnimData *adt, float ctim
|
||||
short ok= 0;
|
||||
|
||||
/* check if this driver's curve should be skipped */
|
||||
// FIXME: maybe we shouldn't check for muted, though that would make things more confusing, as there's already too many ways to disable?
|
||||
if ((fcu->flag & (FCURVE_MUTED|FCURVE_DISABLED)) == 0)
|
||||
{
|
||||
/* check if driver itself is tagged for recalculation */
|
||||
@@ -514,6 +553,10 @@ void animsys_evaluate_action_group (PointerRNA *ptr, bAction *act, bActionGroup
|
||||
if ELEM(NULL, act, agrp) return;
|
||||
if ((remap) && (remap->target != act)) remap= NULL;
|
||||
|
||||
/* if group is muted, don't evaluated any of the F-Curve */
|
||||
if (agrp->flag & AGRP_MUTED)
|
||||
return;
|
||||
|
||||
/* calculate then execute each curve */
|
||||
for (fcu= agrp->channels.first; (fcu) && (fcu->grp == agrp); fcu= fcu->next)
|
||||
{
|
||||
@@ -540,152 +583,590 @@ void animsys_evaluate_action (PointerRNA *ptr, bAction *act, AnimMapper *remap,
|
||||
/* ***************************************** */
|
||||
/* NLA System - Evaluation */
|
||||
|
||||
/* used for list of strips to accumulate at current time */
|
||||
typedef struct NlaEvalStrip {
|
||||
struct NlaEvalStrip *next, *prev;
|
||||
|
||||
NlaTrack *track; /* track that this strip belongs to */
|
||||
NlaStrip *strip; /* strip that's being used */
|
||||
NlaStrip *sblend; /* strip that's being blended towards (if applicable) */
|
||||
|
||||
short track_index; /* the index of the track within the list */
|
||||
short strip_mode; /* which end of the strip are we looking at */
|
||||
} NlaEvalStrip;
|
||||
|
||||
/* bNlaEvalStrip->strip_mode */
|
||||
enum {
|
||||
NES_TIME_BEFORE = -1,
|
||||
NES_TIME_WITHIN,
|
||||
NES_TIME_AFTER,
|
||||
NES_TIME_AFTER_BLEND
|
||||
} eNlaEvalStrip_StripMode;
|
||||
|
||||
|
||||
/* temp channel for accumulating data from NLA (avoids needing to clear all values first) */
|
||||
// TODO: maybe this will be used as the 'cache' stuff needed for editable values too?
|
||||
typedef struct NlaEvalChannel {
|
||||
struct NlaEvalChannel *next, *prev;
|
||||
|
||||
char *path; /* ready-to-use path (i.e. remapped already) */
|
||||
int array_index; /* if applicable... */
|
||||
|
||||
float value; /* value of this channel */
|
||||
} NlaEvalChannel;
|
||||
|
||||
|
||||
/* ---------------------- */
|
||||
|
||||
/* evaluate the F-Curves controlling settings for the NLA-strips (currently, not relinkable) */
|
||||
static void nlastrip_evaluate_fcurves (NlaStrip *strip, float ctime)
|
||||
/* calculate influence of strip based for given frame based on blendin/out values */
|
||||
static float nlastrip_get_influence (NlaStrip *strip, float cframe)
|
||||
{
|
||||
//PointerRNA actstrip_ptr;
|
||||
//FCurve *fcu;
|
||||
/* sanity checks - normalise the blendin/out values? */
|
||||
strip->blendin= (float)fabs(strip->blendin);
|
||||
strip->blendout= (float)fabs(strip->blendout);
|
||||
|
||||
/* create RNA-pointer needed to set values */
|
||||
//RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &actstrip_ptr);
|
||||
|
||||
/* execute these settings as per normal */
|
||||
//animsys_evaluate_fcurves(&actstrip_ptr, &strip->fcurves, NULL, ctime);
|
||||
/* result depends on where frame is in respect to blendin/out values */
|
||||
if (IS_EQ(strip->blendin, 0)==0 && (cframe <= (strip->start + strip->blendin))) {
|
||||
/* there is some blend-in */
|
||||
return (float)fabs(cframe - strip->start) / (strip->blendin);
|
||||
}
|
||||
else if (IS_EQ(strip->blendout, 0)==0 && (cframe >= (strip->end - strip->blendout))) {
|
||||
/* there is some blend-out */
|
||||
return (float)fabs(strip->end - cframe) / (strip->blendout);
|
||||
}
|
||||
else {
|
||||
/* in the middle of the strip, we should be full strength */
|
||||
return 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* gets the strip active at the current time for a track */
|
||||
static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index, float ctime)
|
||||
/* evaluate the evaluation time and influence for the strip, storing the results in the strip */
|
||||
static void nlastrip_evaluate_controls (NlaStrip *strip, float ctime)
|
||||
{
|
||||
NlaStrip *strip, *astrip=NULL, *bstrip=NULL;
|
||||
/* firstly, analytically generate values for influence and time (if applicable) */
|
||||
if ((strip->flag & NLASTRIP_FLAG_USR_TIME) == 0)
|
||||
strip->strip_time= nlastrip_get_frame(strip, ctime, NLATIME_CONVERT_EVAL);
|
||||
if ((strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) == 0)
|
||||
strip->influence= nlastrip_get_influence(strip, ctime);
|
||||
|
||||
/* now strip's evaluate F-Curves for these settings (if applicable) */
|
||||
if (strip->fcurves.first) {
|
||||
PointerRNA strip_ptr;
|
||||
|
||||
/* create RNA-pointer needed to set values */
|
||||
RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr);
|
||||
|
||||
/* execute these settings as per normal */
|
||||
animsys_evaluate_fcurves(&strip_ptr, &strip->fcurves, NULL, ctime);
|
||||
}
|
||||
}
|
||||
|
||||
/* gets the strip active at the current time for a list of strips for evaluation purposes */
|
||||
NlaEvalStrip *nlastrips_ctime_get_strip (ListBase *list, ListBase *strips, short index, float ctime)
|
||||
{
|
||||
NlaStrip *strip, *estrip=NULL;
|
||||
NlaEvalStrip *nes;
|
||||
short side= 0;
|
||||
|
||||
/* skip if track is muted */
|
||||
if (nlt->flag & NLATRACK_MUTED)
|
||||
return;
|
||||
|
||||
/* loop over strips, checking if they fall within the range */
|
||||
for (strip= nlt->strips.first; strip; strip= strip->next) {
|
||||
/* only consider if:
|
||||
* - current time occurs within strip's extents
|
||||
* - current time occurs before strip (if it is the first)
|
||||
* - current time occurs after strip (if hold is on)
|
||||
* - current time occurs between strips (1st of those isn't holding) - blend!
|
||||
*/
|
||||
if (IN_RANGE(ctime, strip->start, strip->end)) {
|
||||
astrip= strip;
|
||||
for (strip= strips->first; strip; strip= strip->next) {
|
||||
/* check if current time occurs within this strip */
|
||||
if (IN_RANGE_INCL(ctime, strip->start, strip->end)) {
|
||||
/* this strip is active, so try to use it */
|
||||
estrip= strip;
|
||||
side= NES_TIME_WITHIN;
|
||||
break;
|
||||
}
|
||||
else if (ctime < strip->start) {
|
||||
if (strip == nlt->strips.first) {
|
||||
astrip= strip;
|
||||
|
||||
/* if time occurred before current strip... */
|
||||
if (ctime < strip->start) {
|
||||
if (strip == strips->first) {
|
||||
/* before first strip - only try to use it if it extends backwards in time too */
|
||||
if (strip->extendmode == NLASTRIP_EXTEND_HOLD)
|
||||
estrip= strip;
|
||||
|
||||
/* side is 'before' regardless of whether there's a useful strip */
|
||||
side= NES_TIME_BEFORE;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
astrip= strip->prev;
|
||||
/* before next strip - previous strip has ended, but next hasn't begun,
|
||||
* so blending mode depends on whether strip is being held or not...
|
||||
* - only occurs when no transition strip added, otherwise the transition would have
|
||||
* been picked up above...
|
||||
*/
|
||||
strip= strip->prev;
|
||||
|
||||
if (astrip->flag & NLASTRIP_HOLDLASTFRAME) {
|
||||
side= NES_TIME_AFTER;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
bstrip= strip;
|
||||
side= NES_TIME_AFTER_BLEND;
|
||||
break;
|
||||
}
|
||||
if (strip->extendmode != NLASTRIP_EXTEND_NOTHING)
|
||||
estrip= strip;
|
||||
side= NES_TIME_AFTER;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* if time occurred after current strip... */
|
||||
if (ctime > strip->end) {
|
||||
/* only if this is the last strip should we do anything, and only if that is being held */
|
||||
if (strip == strips->last) {
|
||||
if (strip->extendmode != NLASTRIP_EXTEND_NOTHING)
|
||||
estrip= strip;
|
||||
|
||||
side= NES_TIME_AFTER;
|
||||
break;
|
||||
}
|
||||
|
||||
/* otherwise, skip... as the 'before' case will catch it more elegantly! */
|
||||
}
|
||||
}
|
||||
|
||||
/* check if strip has been found (and whether it has data worth considering) */
|
||||
if (ELEM(NULL, astrip, astrip->act))
|
||||
return;
|
||||
if (astrip->flag & NLASTRIP_MUTE)
|
||||
return;
|
||||
|
||||
/* check if blending between strips */
|
||||
if (side == NES_TIME_AFTER_BLEND) {
|
||||
/* blending between strips... so calculate influence+act_time of both */
|
||||
nlastrip_evaluate_fcurves(astrip, ctime);
|
||||
nlastrip_evaluate_fcurves(bstrip, ctime);
|
||||
/* check if a valid strip was found
|
||||
* - must not be muted (i.e. will have contribution
|
||||
*/
|
||||
if ((estrip == NULL) || (estrip->flag & NLASTRIP_FLAG_MUTED))
|
||||
return NULL;
|
||||
|
||||
if ((astrip->influence <= 0.0f) && (bstrip->influence <= 0.0f))
|
||||
return;
|
||||
}
|
||||
else {
|
||||
/* calculate/set the influence+act_time of this strip - don't consider if 0 influence */
|
||||
nlastrip_evaluate_fcurves(astrip, ctime);
|
||||
|
||||
if (astrip->influence <= 0.0f)
|
||||
return;
|
||||
/* if ctime was not within the boundaries of the strip, clamp! */
|
||||
switch (side) {
|
||||
case NES_TIME_BEFORE: /* extend first frame only */
|
||||
ctime= estrip->start;
|
||||
break;
|
||||
case NES_TIME_AFTER: /* extend last frame only */
|
||||
ctime= estrip->end;
|
||||
break;
|
||||
}
|
||||
|
||||
/* evaluate strip's evaluation controls
|
||||
* - skip if no influence (i.e. same effect as muting the strip)
|
||||
* - negative influence is not supported yet... how would that be defined?
|
||||
*/
|
||||
// TODO: this sounds a bit hacky having a few isolated F-Curves stuck on some data it operates on...
|
||||
nlastrip_evaluate_controls(estrip, ctime);
|
||||
if (estrip->influence <= 0.0f)
|
||||
return NULL;
|
||||
|
||||
/* check if strip has valid data to evaluate,
|
||||
* and/or perform any additional type-specific actions
|
||||
*/
|
||||
switch (estrip->type) {
|
||||
case NLASTRIP_TYPE_CLIP:
|
||||
/* clip must have some action to evaluate */
|
||||
if (estrip->act == NULL)
|
||||
return NULL;
|
||||
break;
|
||||
case NLASTRIP_TYPE_TRANSITION:
|
||||
/* there must be strips to transition from and to (i.e. prev and next required) */
|
||||
if (ELEM(NULL, estrip->prev, estrip->next))
|
||||
return NULL;
|
||||
|
||||
/* evaluate controls for the relevant extents of the bordering strips... */
|
||||
nlastrip_evaluate_controls(estrip->prev, estrip->start);
|
||||
nlastrip_evaluate_controls(estrip->next, estrip->end);
|
||||
break;
|
||||
}
|
||||
|
||||
/* allocate new eval-strip for this strip + add to stack */
|
||||
/* add to list of strips we need to evaluate */
|
||||
nes= MEM_callocN(sizeof(NlaEvalStrip), "NlaEvalStrip");
|
||||
|
||||
nes->track= nlt;
|
||||
nes->strip= astrip;
|
||||
nes->sblend= bstrip;
|
||||
nes->track_index= index;
|
||||
nes->strip= estrip;
|
||||
nes->strip_mode= side;
|
||||
nes->track_index= index;
|
||||
nes->strip_time= estrip->strip_time;
|
||||
|
||||
BLI_addtail(list, nes);
|
||||
if (list)
|
||||
BLI_addtail(list, nes);
|
||||
|
||||
return nes;
|
||||
}
|
||||
|
||||
/* ---------------------- */
|
||||
|
||||
/* evaluates the given evaluation strip */
|
||||
// FIXME: will we need the evaluation cache table set up to blend stuff in?
|
||||
// TODO: only evaluate here, but flush in one go using the accumulated channels at end...
|
||||
static void nlastrip_ctime_evaluate (ListBase *channels, NlaEvalStrip *nes, float ctime)
|
||||
/* find an NlaEvalChannel that matches the given criteria
|
||||
* - ptr and prop are the RNA data to find a match for
|
||||
*/
|
||||
static NlaEvalChannel *nlaevalchan_find_match (ListBase *channels, PointerRNA *ptr, PropertyRNA *prop, int array_index)
|
||||
{
|
||||
// 1. (in old code) was to extract 'IPO-channels' from actions
|
||||
// 2. blend between the 'accumulated' data, and the new data
|
||||
NlaEvalChannel *nec;
|
||||
|
||||
/* sanity check */
|
||||
if (channels == NULL)
|
||||
return NULL;
|
||||
|
||||
/* loop through existing channels, checking for a channel which affects the same property */
|
||||
for (nec= channels->first; nec; nec= nec->next) {
|
||||
/* - comparing the PointerRNA's is done by comparing the pointers
|
||||
* to the actual struct the property resides in, since that all the
|
||||
* other data stored in PointerRNA cannot allow us to definitively
|
||||
* identify the data
|
||||
*/
|
||||
if ((nec->ptr.data == ptr->data) && (nec->prop == prop) && (nec->index == array_index))
|
||||
return nec;
|
||||
}
|
||||
|
||||
/* not found */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* verify that an appropriate NlaEvalChannel for this F-Curve exists */
|
||||
static NlaEvalChannel *nlaevalchan_verify (PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes, FCurve *fcu, short *newChan)
|
||||
{
|
||||
NlaEvalChannel *nec;
|
||||
NlaStrip *strip= nes->strip;
|
||||
PropertyRNA *prop;
|
||||
PointerRNA new_ptr;
|
||||
char *path = NULL;
|
||||
short free_path=0;
|
||||
|
||||
/* sanity checks */
|
||||
if (channels == NULL)
|
||||
return NULL;
|
||||
|
||||
/* get RNA pointer+property info from F-Curve for more convenient handling */
|
||||
/* get path, remapped as appropriate to work in its new environment */
|
||||
free_path= animsys_remap_path(strip->remap, fcu->rna_path, &path);
|
||||
|
||||
/* a valid property must be available, and it must be animateable */
|
||||
if (RNA_path_resolve(ptr, path, &new_ptr, &prop) == 0) {
|
||||
if (G.f & G_DEBUG) printf("NLA Strip Eval: Cannot resolve path \n");
|
||||
return NULL;
|
||||
}
|
||||
/* only ok if animateable */
|
||||
else if (RNA_property_animateable(&new_ptr, prop) == 0) {
|
||||
if (G.f & G_DEBUG) printf("NLA Strip Eval: Property not animateable \n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* try to find a match */
|
||||
nec= nlaevalchan_find_match(channels, &new_ptr, prop, fcu->array_index);
|
||||
|
||||
/* allocate a new struct for this if none found */
|
||||
if (nec == NULL) {
|
||||
nec= MEM_callocN(sizeof(NlaEvalChannel), "NlaEvalChannel");
|
||||
*newChan= 1;
|
||||
BLI_addtail(channels, nec);
|
||||
|
||||
nec->ptr= new_ptr;
|
||||
nec->prop= prop;
|
||||
nec->index= fcu->array_index;
|
||||
}
|
||||
else
|
||||
*newChan= 0;
|
||||
|
||||
/* we can now return */
|
||||
return nec;
|
||||
}
|
||||
|
||||
/* accumulate (i.e. blend) the given value on to the channel it affects */
|
||||
static void nlaevalchan_accumulate (NlaEvalChannel *nec, NlaEvalStrip *nes, short newChan, float value)
|
||||
{
|
||||
NlaStrip *strip= nes->strip;
|
||||
short blendmode= strip->blendmode;
|
||||
float inf= strip->influence;
|
||||
|
||||
/* if channel is new, just store value regardless of blending factors, etc. */
|
||||
if (newChan) {
|
||||
nec->value= value;
|
||||
return;
|
||||
}
|
||||
|
||||
/* if this is being performed as part of transition evaluation, incorporate
|
||||
* an additional weighting factor for the influence
|
||||
*/
|
||||
if (nes->strip_mode == NES_TIME_TRANSITION_END)
|
||||
inf *= nes->strip_time;
|
||||
|
||||
/* premultiply the value by the weighting factor */
|
||||
if (IS_EQ(inf, 0)) return;
|
||||
value *= inf;
|
||||
|
||||
/* perform blending */
|
||||
switch (blendmode) {
|
||||
case NLASTRIP_MODE_ADD:
|
||||
/* simply add the scaled value on to the stack */
|
||||
nec->value += value;
|
||||
break;
|
||||
|
||||
case NLASTRIP_MODE_SUBTRACT:
|
||||
/* simply subtract the scaled value from the stack */
|
||||
nec->value -= value;
|
||||
break;
|
||||
|
||||
case NLASTRIP_MODE_MULTIPLY:
|
||||
/* multiply the scaled value with the stack */
|
||||
nec->value *= value;
|
||||
break;
|
||||
|
||||
case NLASTRIP_MODE_REPLACE:
|
||||
default: // TODO: do we really want to blend by default? it seems more uses might prefer add...
|
||||
/* do linear interpolation
|
||||
* - the influence of the accumulated data (elsewhere, that is called dstweight)
|
||||
* is 1 - influence, since the strip's influence is srcweight
|
||||
*/
|
||||
nec->value= nec->value * (1.0f - inf) + value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* accumulate the results of a temporary buffer with the results of the full-buffer */
|
||||
static void nlaevalchan_buffers_accumulate (ListBase *channels, ListBase *tmp_buffer, NlaEvalStrip *nes)
|
||||
{
|
||||
NlaEvalChannel *nec, *necn, *necd;
|
||||
|
||||
/* optimise - abort if no channels */
|
||||
if (tmp_buffer->first == NULL)
|
||||
return;
|
||||
|
||||
/* accumulate results in tmp_channels buffer to the accumulation buffer */
|
||||
for (nec= tmp_buffer->first; nec; nec= necn) {
|
||||
/* get pointer to next channel in case we remove the current channel from the temp-buffer */
|
||||
necn= nec->next;
|
||||
|
||||
/* try to find an existing matching channel for this setting in the accumulation buffer */
|
||||
necd= nlaevalchan_find_match(channels, &nec->ptr, nec->prop, nec->index);
|
||||
|
||||
/* if there was a matching channel already in the buffer, accumulate to it,
|
||||
* otherwise, add the current channel to the buffer for efficiency
|
||||
*/
|
||||
if (necd)
|
||||
nlaevalchan_accumulate(necd, nes, 0, nec->value);
|
||||
else {
|
||||
BLI_remlink(tmp_buffer, nec);
|
||||
BLI_addtail(channels, nec);
|
||||
}
|
||||
}
|
||||
|
||||
/* free temp-channels that haven't been assimilated into the buffer */
|
||||
BLI_freelistN(tmp_buffer);
|
||||
}
|
||||
|
||||
/* ---------------------- */
|
||||
/* F-Modifier stack joining/separation utilities - should we generalise these for BLI_listbase.h interface? */
|
||||
|
||||
/* Temporarily join two lists of modifiers together, storing the result in a third list */
|
||||
static void nlaeval_fmodifiers_join_stacks (ListBase *result, ListBase *list1, ListBase *list2)
|
||||
{
|
||||
FModifier *fcm1, *fcm2;
|
||||
|
||||
/* if list1 is invalid... */
|
||||
if ELEM(NULL, list1, list1->first) {
|
||||
if (list2 && list2->first) {
|
||||
result->first= list2->first;
|
||||
result->last= list2->last;
|
||||
}
|
||||
}
|
||||
/* if list 2 is invalid... */
|
||||
else if ELEM(NULL, list2, list2->first) {
|
||||
result->first= list1->first;
|
||||
result->last= list1->last;
|
||||
}
|
||||
else {
|
||||
/* list1 should be added first, and list2 second, with the endpoints of these being the endpoints for result
|
||||
* - the original lists must be left unchanged though, as we need that fact for restoring
|
||||
*/
|
||||
result->first= list1->first;
|
||||
result->last= list2->last;
|
||||
|
||||
fcm1= list1->last;
|
||||
fcm2= list2->first;
|
||||
|
||||
fcm1->next= fcm2;
|
||||
fcm2->prev= fcm1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Split two temporary lists of modifiers */
|
||||
static void nlaeval_fmodifiers_split_stacks (ListBase *list1, ListBase *list2)
|
||||
{
|
||||
FModifier *fcm1, *fcm2;
|
||||
|
||||
/* if list1/2 is invalid... just skip */
|
||||
if ELEM(NULL, list1, list2)
|
||||
return;
|
||||
if ELEM(NULL, list1->first, list2->first)
|
||||
return;
|
||||
|
||||
/* get endpoints */
|
||||
fcm1= list1->last;
|
||||
fcm2= list2->first;
|
||||
|
||||
/* clear their links */
|
||||
fcm1->next= NULL;
|
||||
fcm2->prev= NULL;
|
||||
}
|
||||
|
||||
/* ---------------------- */
|
||||
|
||||
/* evaluate action-clip strip */
|
||||
static void nlastrip_evaluate_actionclip (PointerRNA *ptr, ListBase *channels, ListBase *modifiers, NlaEvalStrip *nes)
|
||||
{
|
||||
ListBase tmp_modifiers = {NULL, NULL};
|
||||
NlaStrip *strip= nes->strip;
|
||||
FCurve *fcu;
|
||||
float evaltime;
|
||||
|
||||
/* join this strip's modifiers to the parent's modifiers (own modifiers first) */
|
||||
nlaeval_fmodifiers_join_stacks(&tmp_modifiers, &strip->modifiers, modifiers);
|
||||
|
||||
/* evaluate strip's modifiers which modify time to evaluate the base curves at */
|
||||
evaltime= evaluate_time_fmodifiers(&tmp_modifiers, NULL, 0.0f, strip->strip_time);
|
||||
|
||||
/* evaluate all the F-Curves in the action, saving the relevant pointers to data that will need to be used */
|
||||
for (fcu= strip->act->curves.first; fcu; fcu= fcu->next) {
|
||||
NlaEvalChannel *nec;
|
||||
float value = 0.0f;
|
||||
short newChan = -1;
|
||||
|
||||
/* check if this curve should be skipped */
|
||||
if (fcu->flag & (FCURVE_MUTED|FCURVE_DISABLED))
|
||||
continue;
|
||||
if ((fcu->grp) && (fcu->grp->flag & AGRP_MUTED))
|
||||
continue;
|
||||
|
||||
/* evaluate the F-Curve's value for the time given in the strip
|
||||
* NOTE: we use the modified time here, since strip's F-Curve Modifiers are applied on top of this
|
||||
*/
|
||||
value= evaluate_fcurve(fcu, evaltime);
|
||||
|
||||
/* apply strip's F-Curve Modifiers on this value
|
||||
* NOTE: we apply the strip's original evaluation time not the modified one (as per standard F-Curve eval)
|
||||
*/
|
||||
evaluate_value_fmodifiers(&tmp_modifiers, fcu, &value, strip->strip_time);
|
||||
|
||||
|
||||
/* get an NLA evaluation channel to work with, and accumulate the evaluated value with the value(s)
|
||||
* stored in this channel if it has been used already
|
||||
*/
|
||||
nec= nlaevalchan_verify(ptr, channels, nes, fcu, &newChan);
|
||||
if (nec)
|
||||
nlaevalchan_accumulate(nec, nes, newChan, value);
|
||||
}
|
||||
|
||||
/* unlink this strip's modifiers from the parent's modifiers again */
|
||||
nlaeval_fmodifiers_split_stacks(&strip->modifiers, modifiers);
|
||||
}
|
||||
|
||||
/* evaluate transition strip */
|
||||
static void nlastrip_evaluate_transition (PointerRNA *ptr, ListBase *channels, ListBase *modifiers, NlaEvalStrip *nes)
|
||||
{
|
||||
ListBase tmp_channels = {NULL, NULL};
|
||||
ListBase tmp_modifiers = {NULL, NULL};
|
||||
NlaEvalStrip tmp_nes;
|
||||
NlaStrip *s1, *s2;
|
||||
|
||||
/* join this strip's modifiers to the parent's modifiers (own modifiers first) */
|
||||
nlaeval_fmodifiers_join_stacks(&tmp_modifiers, &nes->strip->modifiers, modifiers);
|
||||
|
||||
/* get the two strips to operate on
|
||||
* - we use the endpoints of the strips directly flanking our strip
|
||||
* using these as the endpoints of the transition (destination and source)
|
||||
* - these should have already been determined to be valid...
|
||||
* - if this strip is being played in reverse, we need to swap these endpoints
|
||||
* otherwise they will be interpolated wrong
|
||||
*/
|
||||
if (nes->strip->flag & NLASTRIP_FLAG_REVERSE) {
|
||||
s1= nes->strip->next;
|
||||
s2= nes->strip->prev;
|
||||
}
|
||||
else {
|
||||
s1= nes->strip->prev;
|
||||
s2= nes->strip->next;
|
||||
}
|
||||
|
||||
/* prepare template for 'evaluation strip'
|
||||
* - based on the transition strip's evaluation strip data
|
||||
* - strip_mode is NES_TIME_TRANSITION_* based on which endpoint
|
||||
* - strip_time is the 'normalised' (i.e. in-strip) time for evaluation,
|
||||
* which doubles up as an additional weighting factor for the strip influences
|
||||
* which allows us to appear to be 'interpolating' between the two extremes
|
||||
*/
|
||||
tmp_nes= *nes;
|
||||
|
||||
/* evaluate these strips into a temp-buffer (tmp_channels) */
|
||||
// FIXME: modifier evalation here needs some work...
|
||||
/* first strip */
|
||||
tmp_nes.strip_mode= NES_TIME_TRANSITION_START;
|
||||
tmp_nes.strip= s1;
|
||||
nlastrip_evaluate_actionclip(ptr, &tmp_channels, &tmp_modifiers, &tmp_nes);
|
||||
|
||||
/* second strip */
|
||||
tmp_nes.strip_mode= NES_TIME_TRANSITION_END;
|
||||
tmp_nes.strip= s2;
|
||||
nlastrip_evaluate_actionclip(ptr, &tmp_channels, &tmp_modifiers, &tmp_nes);
|
||||
|
||||
|
||||
/* assumulate temp-buffer and full-buffer, using the 'real' strip */
|
||||
nlaevalchan_buffers_accumulate(channels, &tmp_channels, nes);
|
||||
|
||||
/* unlink this strip's modifiers from the parent's modifiers again */
|
||||
nlaeval_fmodifiers_split_stacks(&nes->strip->modifiers, modifiers);
|
||||
}
|
||||
|
||||
/* evaluate meta-strip */
|
||||
static void nlastrip_evaluate_meta (PointerRNA *ptr, ListBase *channels, ListBase *modifiers, NlaEvalStrip *nes)
|
||||
{
|
||||
ListBase tmp_channels = {NULL, NULL};
|
||||
ListBase tmp_modifiers = {NULL, NULL};
|
||||
NlaStrip *strip= nes->strip;
|
||||
NlaEvalStrip *tmp_nes;
|
||||
float evaltime;
|
||||
|
||||
/* meta-strip was calculated normally to have some time to be evaluated at
|
||||
* and here we 'look inside' the meta strip, treating it as a decorated window to
|
||||
* it's child strips, which get evaluated as if they were some tracks on a strip
|
||||
* (but with some extra modifiers to apply).
|
||||
*
|
||||
* NOTE: keep this in sync with animsys_evaluate_nla()
|
||||
*/
|
||||
|
||||
/* join this strip's modifiers to the parent's modifiers (own modifiers first) */
|
||||
nlaeval_fmodifiers_join_stacks(&tmp_modifiers, &strip->modifiers, modifiers);
|
||||
|
||||
/* find the child-strip to evaluate */
|
||||
evaltime= (nes->strip_time * (strip->end - strip->start)) + strip->start;
|
||||
tmp_nes= nlastrips_ctime_get_strip(NULL, &strip->strips, -1, evaltime);
|
||||
if (tmp_nes == NULL)
|
||||
return;
|
||||
|
||||
/* evaluate child-strip into tmp_channels buffer before accumulating
|
||||
* in the accumulation buffer
|
||||
*/
|
||||
nlastrip_evaluate(ptr, &tmp_channels, &tmp_modifiers, tmp_nes);
|
||||
|
||||
/* assumulate temp-buffer and full-buffer, using the 'real' strip */
|
||||
nlaevalchan_buffers_accumulate(channels, &tmp_channels, nes);
|
||||
|
||||
/* free temp eval-strip */
|
||||
MEM_freeN(tmp_nes);
|
||||
|
||||
/* unlink this strip's modifiers from the parent's modifiers again */
|
||||
nlaeval_fmodifiers_split_stacks(&strip->modifiers, modifiers);
|
||||
}
|
||||
|
||||
/* evaluates the given evaluation strip */
|
||||
void nlastrip_evaluate (PointerRNA *ptr, ListBase *channels, ListBase *modifiers, NlaEvalStrip *nes)
|
||||
{
|
||||
/* actions to take depend on the type of strip */
|
||||
switch (nes->strip->type) {
|
||||
case NLASTRIP_TYPE_CLIP: /* action-clip */
|
||||
nlastrip_evaluate_actionclip(ptr, channels, modifiers, nes);
|
||||
break;
|
||||
case NLASTRIP_TYPE_TRANSITION: /* transition */
|
||||
nlastrip_evaluate_transition(ptr, channels, modifiers, nes);
|
||||
break;
|
||||
case NLASTRIP_TYPE_META: /* meta */
|
||||
nlastrip_evaluate_meta(ptr, channels, modifiers, nes);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* write the accumulated settings to */
|
||||
static void nladata_flush_channels (PointerRNA *ptr, ListBase *channels)
|
||||
void nladata_flush_channels (ListBase *channels)
|
||||
{
|
||||
NlaEvalChannel *nec;
|
||||
|
||||
/* sanity checks */
|
||||
if (channels == NULL)
|
||||
return;
|
||||
|
||||
/* for each channel with accumulated values, write its value on the property it affects */
|
||||
for (nec= channels->first; nec; nec= nec->next) {
|
||||
PointerRNA *ptr= &nec->ptr;
|
||||
PropertyRNA *prop= nec->prop;
|
||||
int array_index= nec->index;
|
||||
float value= nec->value;
|
||||
|
||||
/* write values - see animsys_write_rna_setting() to sync the code */
|
||||
switch (RNA_property_type(prop))
|
||||
{
|
||||
case PROP_BOOLEAN:
|
||||
if (RNA_property_array_length(prop))
|
||||
RNA_property_boolean_set_index(ptr, prop, array_index, (int)value);
|
||||
else
|
||||
RNA_property_boolean_set(ptr, prop, (int)value);
|
||||
break;
|
||||
case PROP_INT:
|
||||
if (RNA_property_array_length(prop))
|
||||
RNA_property_int_set_index(ptr, prop, array_index, (int)value);
|
||||
else
|
||||
RNA_property_int_set(ptr, prop, (int)value);
|
||||
break;
|
||||
case PROP_FLOAT:
|
||||
if (RNA_property_array_length(prop))
|
||||
RNA_property_float_set_index(ptr, prop, array_index, value);
|
||||
else
|
||||
RNA_property_float_set(ptr, prop, value);
|
||||
break;
|
||||
case PROP_ENUM:
|
||||
RNA_property_enum_set(ptr, prop, (int)value);
|
||||
break;
|
||||
default:
|
||||
// can't do anything with other types of property....
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------- */
|
||||
@@ -703,9 +1184,26 @@ static void animsys_evaluate_nla (PointerRNA *ptr, AnimData *adt, float ctime)
|
||||
ListBase echannels= {NULL, NULL};
|
||||
NlaEvalStrip *nes;
|
||||
|
||||
// TODO: need to zero out all channels used, otherwise we have problems with threadsafety
|
||||
// and also when the user jumps between different times instead of moving sequentially...
|
||||
|
||||
/* 1. get the stack of strips to evaluate at current time (influence calculated here) */
|
||||
for (nlt=adt->nla_tracks.first; nlt; nlt=nlt->next, track_index++)
|
||||
nlatrack_ctime_get_strip(&estrips, nlt, track_index, ctime);
|
||||
for (nlt=adt->nla_tracks.first; nlt; nlt=nlt->next, track_index++) {
|
||||
/* if tweaking is on and this strip is the tweaking track, stop on this one */
|
||||
if ((adt->flag & ADT_NLA_EDIT_ON) && (nlt->flag & NLATRACK_DISABLED))
|
||||
break;
|
||||
|
||||
/* skip if we're only considering a track tagged 'solo' */
|
||||
if ((adt->flag & ADT_NLA_SOLO_TRACK) && (nlt->flag & NLATRACK_SOLO)==0)
|
||||
continue;
|
||||
/* skip if track is muted */
|
||||
if (nlt->flag & NLATRACK_MUTED)
|
||||
continue;
|
||||
|
||||
/* otherwise, get strip to evaluate for this channel */
|
||||
nes= nlastrips_ctime_get_strip(&estrips, &nlt->strips, track_index, ctime);
|
||||
if (nes) nes->track= nlt;
|
||||
}
|
||||
|
||||
/* only continue if there are strips to evaluate */
|
||||
if (estrips.first == NULL)
|
||||
@@ -714,10 +1212,10 @@ static void animsys_evaluate_nla (PointerRNA *ptr, AnimData *adt, float ctime)
|
||||
|
||||
/* 2. for each strip, evaluate then accumulate on top of existing channels, but don't set values yet */
|
||||
for (nes= estrips.first; nes; nes= nes->next)
|
||||
nlastrip_ctime_evaluate(&echannels, nes, ctime);
|
||||
nlastrip_evaluate(ptr, &echannels, NULL, nes);
|
||||
|
||||
/* 3. flush effects of accumulating channels in NLA to the actual data they affect */
|
||||
nladata_flush_channels(ptr, &echannels);
|
||||
nladata_flush_channels(&echannels);
|
||||
|
||||
/* 4. free temporary evaluation data */
|
||||
BLI_freelistN(&estrips);
|
||||
@@ -799,17 +1297,23 @@ void BKE_animsys_evaluate_animdata (ID *id, AnimData *adt, float ctime, short re
|
||||
* - NLA before Active Action, as Active Action behaves as 'tweaking track'
|
||||
* that overrides 'rough' work in NLA
|
||||
*/
|
||||
// TODO: need to double check that this all works correctly
|
||||
if ((recalc & ADT_RECALC_ANIM) || (adt->recalc & ADT_RECALC_ANIM))
|
||||
{
|
||||
/* evaluate NLA data */
|
||||
if ((adt->nla_tracks.first) && !(adt->flag & ADT_NLA_EVAL_OFF))
|
||||
{
|
||||
/* evaluate NLA-stack */
|
||||
animsys_evaluate_nla(&id_ptr, adt, ctime);
|
||||
|
||||
/* evaluate 'active' Action (may be tweaking track) on top of results of NLA-evaluation
|
||||
* - only do this if we're not exclusively evaluating the 'solo' NLA-track
|
||||
*/
|
||||
if ((adt->action) && !(adt->flag & ADT_NLA_SOLO_TRACK))
|
||||
animsys_evaluate_action(&id_ptr, adt->action, adt->remap, ctime);
|
||||
}
|
||||
|
||||
/* evaluate Action data */
|
||||
// FIXME: what if the solo track was not tweaking one, then nla-solo should be checked too?
|
||||
if (adt->action)
|
||||
/* evaluate Active Action only */
|
||||
else if (adt->action)
|
||||
animsys_evaluate_action(&id_ptr, adt->action, adt->remap, ctime);
|
||||
|
||||
/* reset tag */
|
||||
@@ -876,10 +1380,22 @@ void BKE_animsys_evaluate_all_animation (Main *main, float ctime)
|
||||
EVAL_ANIM_IDS(main->camera.first, ADT_RECALC_ANIM);
|
||||
|
||||
/* shapekeys */
|
||||
// TODO: we probably need the same hack as for curves (ctime-hack)
|
||||
EVAL_ANIM_IDS(main->key.first, ADT_RECALC_ANIM);
|
||||
|
||||
/* curves */
|
||||
// TODO...
|
||||
/* we need to perform a special hack here to ensure that the ctime
|
||||
* value of the curve gets set in case there's no animation for that
|
||||
* - it needs to be set before animation is evaluated just so that
|
||||
* animation can successfully override...
|
||||
*/
|
||||
for (id= main->curve.first; id; id= id->next) {
|
||||
AnimData *adt= BKE_animdata_from_id(id);
|
||||
Curve *cu= (Curve *)id;
|
||||
|
||||
cu->ctime= ctime;
|
||||
BKE_animsys_evaluate_animdata(id, adt, ctime, ADT_RECALC_ANIM);
|
||||
}
|
||||
|
||||
/* meshes */
|
||||
// TODO...
|
||||
|
||||
@@ -1,5 +1,30 @@
|
||||
/* Testing code for new animation system in 2.5
|
||||
* Copyright 2009, Joshua Leung
|
||||
/**
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): Joshua Leung (full recode)
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
|
||||
@@ -31,7 +56,7 @@
|
||||
#include "RNA_types.h"
|
||||
|
||||
#ifndef DISABLE_PYTHON
|
||||
#include "BPY_extern.h" /* for BPY_pydriver_eval() */
|
||||
#include "BPY_extern.h"
|
||||
#endif
|
||||
|
||||
#define SMALL -1.0e-10
|
||||
@@ -59,7 +84,7 @@ void free_fcurve (FCurve *fcu)
|
||||
|
||||
/* free extra data - i.e. modifiers, and driver */
|
||||
fcurve_free_driver(fcu);
|
||||
fcurve_free_modifiers(fcu);
|
||||
free_fmodifiers(&fcu->modifiers);
|
||||
|
||||
/* free f-curve itself */
|
||||
MEM_freeN(fcu);
|
||||
@@ -115,7 +140,7 @@ FCurve *copy_fcurve (FCurve *fcu)
|
||||
fcu_d->driver= fcurve_copy_driver(fcu_d->driver);
|
||||
|
||||
/* copy modifiers */
|
||||
fcurve_copy_modifiers(&fcu_d->modifiers, &fcu->modifiers);
|
||||
copy_fmodifiers(&fcu_d->modifiers, &fcu->modifiers);
|
||||
|
||||
/* return new data */
|
||||
return fcu_d;
|
||||
@@ -175,20 +200,6 @@ FCurve *list_find_fcurve (ListBase *list, const char rna_path[], const int array
|
||||
return NULL;
|
||||
}
|
||||
|
||||
short on_keyframe_fcurve(FCurve *fcu, float cfra)
|
||||
{
|
||||
BezTriple *bezt;
|
||||
unsigned i;
|
||||
|
||||
bezt= fcu->bezt;
|
||||
for (i=0; i<fcu->totvert; i++, bezt++) {
|
||||
if (IS_EQ(bezt->vec[1][0], cfra))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Calculate the extents of F-Curve's data */
|
||||
void calc_fcurve_bounds (FCurve *fcu, float *xmin, float *xmax, float *ymin, float *ymax)
|
||||
{
|
||||
@@ -1245,1016 +1256,6 @@ static float fcurve_eval_samples (FCurve *fcu, FPoint *fpts, float evaltime)
|
||||
return cvalue;
|
||||
}
|
||||
|
||||
/* ******************************** F-Curve Modifiers ********************************* */
|
||||
|
||||
/* Template --------------------------- */
|
||||
|
||||
/* Each modifier defines a set of functions, which will be called at the appropriate
|
||||
* times. In addition to this, each modifier should have a type-info struct, where
|
||||
* its functions are attached for use.
|
||||
*/
|
||||
|
||||
/* Template for type-info data:
|
||||
* - make a copy of this when creating new modifiers, and just change the functions
|
||||
* pointed to as necessary
|
||||
* - although the naming of functions doesn't matter, it would help for code
|
||||
* readability, to follow the same naming convention as is presented here
|
||||
* - any functions that a constraint doesn't need to define, don't define
|
||||
* for such cases, just use NULL
|
||||
* - these should be defined after all the functions have been defined, so that
|
||||
* forward-definitions/prototypes don't need to be used!
|
||||
* - keep this copy #if-def'd so that future constraints can get based off this
|
||||
*/
|
||||
#if 0
|
||||
static FModifierTypeInfo FMI_MODNAME = {
|
||||
FMODIFIER_TYPE_MODNAME, /* type */
|
||||
sizeof(FMod_ModName), /* size */
|
||||
FMI_TYPE_SOME_ACTION, /* action type */
|
||||
FMI_REQUIRES_SOME_REQUIREMENT, /* requirements */
|
||||
"Modifier Name", /* name */
|
||||
"FMod_ModName", /* struct name */
|
||||
fcm_modname_free, /* free data */
|
||||
fcm_modname_relink, /* relink data */
|
||||
fcm_modname_copy, /* copy data */
|
||||
fcm_modname_new_data, /* new data */
|
||||
fcm_modname_verify, /* verify */
|
||||
fcm_modname_time, /* evaluate time */
|
||||
fcm_modname_evaluate /* evaluate */
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Generator F-Curve Modifier --------------------------- */
|
||||
|
||||
/* Generators available:
|
||||
* 1) simple polynomial generator:
|
||||
* - Exanded form - (y = C[0]*(x^(n)) + C[1]*(x^(n-1)) + ... + C[n])
|
||||
* - Factorised form - (y = (C[0][0]*x + C[0][1]) * (C[1][0]*x + C[1][1]) * ... * (C[n][0]*x + C[n][1]))
|
||||
* 2) simple builin 'functions':
|
||||
* of the form (y = C[0] * fn( C[1]*x + C[2] ) + C[3])
|
||||
* where fn() can be any one of:
|
||||
* sin, cos, tan, ln, sqrt
|
||||
* 3) expression...
|
||||
*/
|
||||
|
||||
static void fcm_generator_free (FModifier *fcm)
|
||||
{
|
||||
FMod_Generator *data= (FMod_Generator *)fcm->data;
|
||||
|
||||
/* free polynomial coefficients array */
|
||||
if (data->coefficients)
|
||||
MEM_freeN(data->coefficients);
|
||||
}
|
||||
|
||||
static void fcm_generator_copy (FModifier *fcm, FModifier *src)
|
||||
{
|
||||
FMod_Generator *gen= (FMod_Generator *)fcm->data;
|
||||
FMod_Generator *ogen= (FMod_Generator *)src->data;
|
||||
|
||||
/* copy coefficients array? */
|
||||
if (ogen->coefficients)
|
||||
gen->coefficients= MEM_dupallocN(ogen->coefficients);
|
||||
}
|
||||
|
||||
static void fcm_generator_new_data (void *mdata)
|
||||
{
|
||||
FMod_Generator *data= (FMod_Generator *)mdata;
|
||||
float *cp;
|
||||
|
||||
/* set default generator to be linear 0-1 (gradient = 1, y-offset = 0) */
|
||||
data->poly_order= 1;
|
||||
data->arraysize= 2;
|
||||
cp= data->coefficients= MEM_callocN(sizeof(float)*2, "FMod_Generator_Coefs");
|
||||
cp[0] = 0; // y-offset
|
||||
cp[1] = 1; // gradient
|
||||
}
|
||||
|
||||
static void fcm_generator_verify (FModifier *fcm)
|
||||
{
|
||||
FMod_Generator *data= (FMod_Generator *)fcm->data;
|
||||
|
||||
/* requirements depend on mode */
|
||||
switch (data->mode) {
|
||||
case FCM_GENERATOR_POLYNOMIAL: /* expanded polynomial expression */
|
||||
{
|
||||
/* arraysize needs to be order+1, so resize if not */
|
||||
if (data->arraysize != (data->poly_order+1)) {
|
||||
float *nc;
|
||||
|
||||
/* make new coefficients array, and copy over as much data as can fit */
|
||||
nc= MEM_callocN(sizeof(float)*(data->poly_order+1), "FMod_Generator_Coefs");
|
||||
|
||||
if (data->coefficients) {
|
||||
if (data->arraysize > (data->poly_order+1))
|
||||
memcpy(nc, data->coefficients, sizeof(float)*(data->poly_order+1));
|
||||
else
|
||||
memcpy(nc, data->coefficients, sizeof(float)*data->arraysize);
|
||||
|
||||
/* free the old data */
|
||||
MEM_freeN(data->coefficients);
|
||||
}
|
||||
|
||||
/* set the new data */
|
||||
data->coefficients= nc;
|
||||
data->arraysize= data->poly_order+1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* expanded polynomial expression */
|
||||
{
|
||||
/* arraysize needs to be 2*order, so resize if not */
|
||||
if (data->arraysize != (data->poly_order * 2)) {
|
||||
float *nc;
|
||||
|
||||
/* make new coefficients array, and copy over as much data as can fit */
|
||||
nc= MEM_callocN(sizeof(float)*(data->poly_order*2), "FMod_Generator_Coefs");
|
||||
|
||||
if (data->coefficients) {
|
||||
if (data->arraysize > (data->poly_order * 2))
|
||||
memcpy(nc, data->coefficients, sizeof(float)*(data->poly_order * 2));
|
||||
else
|
||||
memcpy(nc, data->coefficients, sizeof(float)*data->arraysize);
|
||||
|
||||
/* free the old data */
|
||||
MEM_freeN(data->coefficients);
|
||||
}
|
||||
|
||||
/* set the new data */
|
||||
data->coefficients= nc;
|
||||
data->arraysize= data->poly_order * 2;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case FCM_GENERATOR_FUNCTION: /* builtin function */
|
||||
{
|
||||
/* arraysize needs to be 4*/
|
||||
if (data->arraysize != 4) {
|
||||
float *nc;
|
||||
|
||||
/* free the old data */
|
||||
if (data->coefficients)
|
||||
MEM_freeN(data->coefficients);
|
||||
|
||||
/* make new coefficients array, and init using default values */
|
||||
nc= data->coefficients= MEM_callocN(sizeof(float)*4, "FMod_Generator_Coefs");
|
||||
data->arraysize= 4;
|
||||
|
||||
nc[0]= 1.0f;
|
||||
nc[1]= 1.0f;
|
||||
nc[2]= 0.0f;
|
||||
nc[3]= 0.0f;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void fcm_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
|
||||
{
|
||||
FMod_Generator *data= (FMod_Generator *)fcm->data;
|
||||
|
||||
/* behaviour depends on mode
|
||||
* NOTE: the data in its default state is fine too
|
||||
*/
|
||||
switch (data->mode) {
|
||||
case FCM_GENERATOR_POLYNOMIAL: /* expanded polynomial expression */
|
||||
{
|
||||
/* we overwrite cvalue with the sum of the polynomial */
|
||||
float *powers = MEM_callocN(sizeof(float)*data->arraysize, "Poly Powers");
|
||||
float value= 0.0f;
|
||||
unsigned int i;
|
||||
|
||||
/* for each x^n, precalculate value based on previous one first... this should be
|
||||
* faster that calling pow() for each entry
|
||||
*/
|
||||
for (i=0; i < data->arraysize; i++) {
|
||||
/* first entry is x^0 = 1, otherwise, calculate based on previous */
|
||||
if (i)
|
||||
powers[i]= powers[i-1] * evaltime;
|
||||
else
|
||||
powers[0]= 1;
|
||||
}
|
||||
|
||||
/* for each coefficient, add to value, which we'll write to *cvalue in one go */
|
||||
for (i=0; i < data->arraysize; i++)
|
||||
value += data->coefficients[i] * powers[i];
|
||||
|
||||
/* only if something changed, write *cvalue in one go */
|
||||
if (data->poly_order) {
|
||||
if (data->flag & FCM_GENERATOR_ADDITIVE)
|
||||
*cvalue += value;
|
||||
else
|
||||
*cvalue= value;
|
||||
}
|
||||
|
||||
/* cleanup */
|
||||
if (powers)
|
||||
MEM_freeN(powers);
|
||||
}
|
||||
break;
|
||||
|
||||
case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* factorised polynomial */
|
||||
{
|
||||
float value= 1.0f, *cp=NULL;
|
||||
unsigned int i;
|
||||
|
||||
/* for each coefficient pair, solve for that bracket before accumulating in value by multiplying */
|
||||
for (cp=data->coefficients, i=0; (cp) && (i < data->poly_order); cp+=2, i++)
|
||||
value *= (cp[0]*evaltime + cp[1]);
|
||||
|
||||
/* only if something changed, write *cvalue in one go */
|
||||
if (data->poly_order) {
|
||||
if (data->flag & FCM_GENERATOR_ADDITIVE)
|
||||
*cvalue += value;
|
||||
else
|
||||
*cvalue= value;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case FCM_GENERATOR_FUNCTION: /* builtin function */
|
||||
{
|
||||
double arg= data->coefficients[1]*evaltime + data->coefficients[2];
|
||||
double (*fn)(double v) = NULL;
|
||||
|
||||
/* get function pointer to the func to use:
|
||||
* WARNING: must perform special argument validation hereto guard against crashes
|
||||
*/
|
||||
switch (data->func_type)
|
||||
{
|
||||
/* simple ones */
|
||||
case FCM_GENERATOR_FN_SIN: /* sine wave */
|
||||
fn= sin;
|
||||
break;
|
||||
case FCM_GENERATOR_FN_COS: /* cosine wave */
|
||||
fn= cos;
|
||||
break;
|
||||
|
||||
/* validation required */
|
||||
case FCM_GENERATOR_FN_TAN: /* tangent wave */
|
||||
{
|
||||
/* check that argument is not on one of the discontinuities (i.e. 90deg, 270 deg, etc) */
|
||||
if IS_EQ(fmod((arg - M_PI_2), M_PI), 0.0) {
|
||||
if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0)
|
||||
*cvalue = 0.0f; /* no value possible here */
|
||||
}
|
||||
else
|
||||
fn= tan;
|
||||
}
|
||||
break;
|
||||
case FCM_GENERATOR_FN_LN: /* natural log */
|
||||
{
|
||||
/* check that value is greater than 1? */
|
||||
if (arg > 1.0f) {
|
||||
fn= log;
|
||||
}
|
||||
else {
|
||||
if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0)
|
||||
*cvalue = 0.0f; /* no value possible here */
|
||||
}
|
||||
}
|
||||
break;
|
||||
case FCM_GENERATOR_FN_SQRT: /* square root */
|
||||
{
|
||||
/* no negative numbers */
|
||||
if (arg > 0.0f) {
|
||||
fn= sqrt;
|
||||
}
|
||||
else {
|
||||
if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0)
|
||||
*cvalue = 0.0f; /* no value possible here */
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("Invalid Function-Generator for F-Modifier - %d \n", data->func_type);
|
||||
}
|
||||
|
||||
/* execute function callback to set value if appropriate */
|
||||
if (fn) {
|
||||
float value= (float)(data->coefficients[0]*fn(arg) + data->coefficients[3]);
|
||||
|
||||
if (data->flag & FCM_GENERATOR_ADDITIVE)
|
||||
*cvalue += value;
|
||||
else
|
||||
*cvalue= value;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
#ifndef DISABLE_PYTHON
|
||||
case FCM_GENERATOR_EXPRESSION: /* py-expression */
|
||||
// TODO...
|
||||
break;
|
||||
#endif /* DISABLE_PYTHON */
|
||||
}
|
||||
}
|
||||
|
||||
static FModifierTypeInfo FMI_GENERATOR = {
|
||||
FMODIFIER_TYPE_GENERATOR, /* type */
|
||||
sizeof(FMod_Generator), /* size */
|
||||
FMI_TYPE_GENERATE_CURVE, /* action type */
|
||||
FMI_REQUIRES_NOTHING, /* requirements */
|
||||
"Generator", /* name */
|
||||
"FMod_Generator", /* struct name */
|
||||
fcm_generator_free, /* free data */
|
||||
fcm_generator_copy, /* copy data */
|
||||
fcm_generator_new_data, /* new data */
|
||||
fcm_generator_verify, /* verify */
|
||||
NULL, /* evaluate time */
|
||||
fcm_generator_evaluate /* evaluate */
|
||||
};
|
||||
|
||||
/* Envelope F-Curve Modifier --------------------------- */
|
||||
|
||||
static void fcm_envelope_free (FModifier *fcm)
|
||||
{
|
||||
FMod_Envelope *env= (FMod_Envelope *)fcm->data;
|
||||
|
||||
/* free envelope data array */
|
||||
if (env->data)
|
||||
MEM_freeN(env->data);
|
||||
}
|
||||
|
||||
static void fcm_envelope_copy (FModifier *fcm, FModifier *src)
|
||||
{
|
||||
FMod_Envelope *env= (FMod_Envelope *)fcm->data;
|
||||
FMod_Envelope *oenv= (FMod_Envelope *)src->data;
|
||||
|
||||
/* copy envelope data array */
|
||||
if (oenv->data)
|
||||
env->data= MEM_dupallocN(oenv->data);
|
||||
}
|
||||
|
||||
static void fcm_envelope_new_data (void *mdata)
|
||||
{
|
||||
FMod_Envelope *env= (FMod_Envelope *)mdata;
|
||||
|
||||
/* set default min/max ranges */
|
||||
env->min= -1.0f;
|
||||
env->max= 1.0f;
|
||||
}
|
||||
|
||||
static void fcm_envelope_verify (FModifier *fcm)
|
||||
{
|
||||
FMod_Envelope *env= (FMod_Envelope *)fcm->data;
|
||||
|
||||
/* if the are points, perform bubble-sort on them, as user may have changed the order */
|
||||
if (env->data) {
|
||||
// XXX todo...
|
||||
}
|
||||
}
|
||||
|
||||
static void fcm_envelope_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
|
||||
{
|
||||
FMod_Envelope *env= (FMod_Envelope *)fcm->data;
|
||||
FCM_EnvelopeData *fed, *prevfed, *lastfed;
|
||||
float min=0.0f, max=0.0f, fac=0.0f;
|
||||
int a;
|
||||
|
||||
/* get pointers */
|
||||
if (env->data == NULL) return;
|
||||
prevfed= env->data;
|
||||
fed= prevfed + 1;
|
||||
lastfed= prevfed + (env->totvert-1);
|
||||
|
||||
/* get min/max values for envelope at evaluation time (relative to mid-value) */
|
||||
if (prevfed->time >= evaltime) {
|
||||
/* before or on first sample, so just extend value */
|
||||
min= prevfed->min;
|
||||
max= prevfed->max;
|
||||
}
|
||||
else if (lastfed->time <= evaltime) {
|
||||
/* after or on last sample, so just extend value */
|
||||
min= lastfed->min;
|
||||
max= lastfed->max;
|
||||
}
|
||||
else {
|
||||
/* evaltime occurs somewhere between segments */
|
||||
// TODO: implement binary search for this to make it faster?
|
||||
for (a=0; prevfed && fed && (a < env->totvert-1); a++, prevfed=fed, fed++) {
|
||||
/* evaltime occurs within the interval defined by these two envelope points */
|
||||
if ((prevfed->time <= evaltime) && (fed->time >= evaltime)) {
|
||||
float afac, bfac, diff;
|
||||
|
||||
diff= fed->time - prevfed->time;
|
||||
afac= (evaltime - prevfed->time) / diff;
|
||||
bfac= (fed->time - evaltime) / diff;
|
||||
|
||||
min= bfac*prevfed->min + afac*fed->min;
|
||||
max= bfac*prevfed->max + afac*fed->max;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* adjust *cvalue
|
||||
* - fac is the ratio of how the current y-value corresponds to the reference range
|
||||
* - thus, the new value is found by mapping the old range to the new!
|
||||
*/
|
||||
fac= (*cvalue - (env->midval + env->min)) / (env->max - env->min);
|
||||
*cvalue= min + fac*(max - min);
|
||||
}
|
||||
|
||||
static FModifierTypeInfo FMI_ENVELOPE = {
|
||||
FMODIFIER_TYPE_ENVELOPE, /* type */
|
||||
sizeof(FMod_Envelope), /* size */
|
||||
FMI_TYPE_REPLACE_VALUES, /* action type */
|
||||
0, /* requirements */
|
||||
"Envelope", /* name */
|
||||
"FMod_Envelope", /* struct name */
|
||||
fcm_envelope_free, /* free data */
|
||||
fcm_envelope_copy, /* copy data */
|
||||
fcm_envelope_new_data, /* new data */
|
||||
fcm_envelope_verify, /* verify */
|
||||
NULL, /* evaluate time */
|
||||
fcm_envelope_evaluate /* evaluate */
|
||||
};
|
||||
|
||||
/* Cycles F-Curve Modifier --------------------------- */
|
||||
|
||||
/* This modifier changes evaltime to something that exists within the curve's frame-range,
|
||||
* then re-evaluates modifier stack up to this point using the new time. This re-entrant behaviour
|
||||
* is very likely to be more time-consuming than the original approach... (which was tighly integrated into
|
||||
* the calculation code...).
|
||||
*
|
||||
* NOTE: this needs to be at the start of the stack to be of use, as it needs to know the extents of the keyframes/sample-data
|
||||
* Possible TODO - store length of cycle information that can be initialised from the extents of the keyframes/sample-data, and adjusted
|
||||
* as appropriate
|
||||
*/
|
||||
|
||||
/* temp data used during evaluation */
|
||||
typedef struct tFCMED_Cycles {
|
||||
float cycyofs; /* y-offset to apply */
|
||||
} tFCMED_Cycles;
|
||||
|
||||
static void fcm_cycles_new_data (void *mdata)
|
||||
{
|
||||
FMod_Cycles *data= (FMod_Cycles *)mdata;
|
||||
|
||||
/* turn on cycles by default */
|
||||
data->before_mode= data->after_mode= FCM_EXTRAPOLATE_CYCLIC;
|
||||
}
|
||||
|
||||
static float fcm_cycles_time (FCurve *fcu, FModifier *fcm, float cvalue, float evaltime)
|
||||
{
|
||||
FMod_Cycles *data= (FMod_Cycles *)fcm->data;
|
||||
float prevkey[2], lastkey[2], cycyofs=0.0f;
|
||||
short side=0, mode=0;
|
||||
int cycles=0;
|
||||
|
||||
/* check if modifier is first in stack, otherwise disable ourself... */
|
||||
// FIXME...
|
||||
if (fcm->prev) {
|
||||
fcm->flag |= FMODIFIER_FLAG_DISABLED;
|
||||
return evaltime;
|
||||
}
|
||||
|
||||
/* calculate new evaltime due to cyclic interpolation */
|
||||
if (fcu && fcu->bezt) {
|
||||
BezTriple *prevbezt= fcu->bezt;
|
||||
BezTriple *lastbezt= prevbezt + fcu->totvert-1;
|
||||
|
||||
prevkey[0]= prevbezt->vec[1][0];
|
||||
prevkey[1]= prevbezt->vec[1][1];
|
||||
|
||||
lastkey[0]= lastbezt->vec[1][0];
|
||||
lastkey[1]= lastbezt->vec[1][1];
|
||||
}
|
||||
else if (fcu && fcu->fpt) {
|
||||
FPoint *prevfpt= fcu->fpt;
|
||||
FPoint *lastfpt= prevfpt + fcu->totvert-1;
|
||||
|
||||
prevkey[0]= prevfpt->vec[0];
|
||||
prevkey[1]= prevfpt->vec[1];
|
||||
|
||||
lastkey[0]= lastfpt->vec[0];
|
||||
lastkey[1]= lastfpt->vec[1];
|
||||
}
|
||||
else
|
||||
return evaltime;
|
||||
|
||||
/* check if modifier will do anything
|
||||
* 1) if in data range, definitely don't do anything
|
||||
* 2) if before first frame or after last frame, make sure some cycling is in use
|
||||
*/
|
||||
if (evaltime < prevkey[0]) {
|
||||
if (data->before_mode) {
|
||||
side= -1;
|
||||
mode= data->before_mode;
|
||||
cycles= data->before_cycles;
|
||||
}
|
||||
}
|
||||
else if (evaltime > lastkey[0]) {
|
||||
if (data->after_mode) {
|
||||
side= 1;
|
||||
mode= data->after_mode;
|
||||
cycles= data->after_cycles;
|
||||
}
|
||||
}
|
||||
if ELEM(0, side, mode)
|
||||
return evaltime;
|
||||
|
||||
/* find relative place within a cycle */
|
||||
{
|
||||
float cycdx=0, cycdy=0, ofs=0;
|
||||
float cycle= 0;
|
||||
|
||||
/* ofs is start frame of cycle */
|
||||
ofs= prevkey[0];
|
||||
|
||||
/* calculate period and amplitude (total height) of a cycle */
|
||||
cycdx= lastkey[0] - prevkey[0];
|
||||
cycdy= lastkey[1] - prevkey[1];
|
||||
|
||||
/* check if cycle is infinitely small, to be point of being impossible to use */
|
||||
if (cycdx == 0)
|
||||
return evaltime;
|
||||
|
||||
/* calculate the 'number' of the cycle */
|
||||
cycle= ((float)side * (evaltime - ofs) / cycdx);
|
||||
|
||||
/* check that cyclic is still enabled for the specified time */
|
||||
if (cycles == 0) {
|
||||
/* catch this case so that we don't exit when we have cycles=0
|
||||
* as this indicates infinite cycles...
|
||||
*/
|
||||
}
|
||||
else if (cycle > (cycles+1)) {
|
||||
/* we are too far away from range to evaluate
|
||||
* TODO: but we should still hold last value...
|
||||
*/
|
||||
return evaltime;
|
||||
}
|
||||
|
||||
/* check if 'cyclic extrapolation', and thus calculate y-offset for this cycle */
|
||||
if (mode == FCM_EXTRAPOLATE_CYCLIC_OFFSET) {
|
||||
cycyofs = (float)floor((evaltime - ofs) / cycdx);
|
||||
cycyofs *= cycdy;
|
||||
}
|
||||
|
||||
/* calculate where in the cycle we are (overwrite evaltime to reflect this) */
|
||||
if ((mode == FCM_EXTRAPOLATE_MIRROR) && ((int)(cycle) % 2)) {
|
||||
/* when 'mirror' option is used and cycle number is odd, this cycle is played in reverse
|
||||
* - for 'before' extrapolation, we need to flip in a different way, otherwise values past
|
||||
* then end of the curve get referenced (result of fmod will be negative, and with different phase)
|
||||
*/
|
||||
if (side < 0)
|
||||
evaltime= (float)(prevkey[0] - fmod(evaltime-ofs, cycdx));
|
||||
else
|
||||
evaltime= (float)(lastkey[0] - fmod(evaltime-ofs, cycdx));
|
||||
}
|
||||
else {
|
||||
/* the cycle is played normally... */
|
||||
evaltime= (float)(fmod(evaltime-ofs, cycdx) + ofs);
|
||||
}
|
||||
if (evaltime < ofs) evaltime += cycdx;
|
||||
}
|
||||
|
||||
/* store temp data if needed */
|
||||
if (mode == FCM_EXTRAPOLATE_CYCLIC_OFFSET) {
|
||||
tFCMED_Cycles *edata;
|
||||
|
||||
/* for now, this is just a float, but we could get more stuff... */
|
||||
fcm->edata= edata= MEM_callocN(sizeof(tFCMED_Cycles), "tFCMED_Cycles");
|
||||
edata->cycyofs= cycyofs;
|
||||
}
|
||||
|
||||
/* return the new frame to evaluate */
|
||||
return evaltime;
|
||||
}
|
||||
|
||||
static void fcm_cycles_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
|
||||
{
|
||||
tFCMED_Cycles *edata= (tFCMED_Cycles *)fcm->edata;
|
||||
|
||||
/* use temp data */
|
||||
if (edata) {
|
||||
/* add cyclic offset - no need to check for now, otherwise the data wouldn't exist! */
|
||||
*cvalue += edata->cycyofs;
|
||||
|
||||
/* free temp data */
|
||||
MEM_freeN(edata);
|
||||
fcm->edata= NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static FModifierTypeInfo FMI_CYCLES = {
|
||||
FMODIFIER_TYPE_CYCLES, /* type */
|
||||
sizeof(FMod_Cycles), /* size */
|
||||
FMI_TYPE_EXTRAPOLATION, /* action type */
|
||||
FMI_REQUIRES_ORIGINAL_DATA, /* requirements */
|
||||
"Cycles", /* name */
|
||||
"FMod_Cycles", /* struct name */
|
||||
NULL, /* free data */
|
||||
NULL, /* copy data */
|
||||
fcm_cycles_new_data, /* new data */
|
||||
NULL /*fcm_cycles_verify*/, /* verify */
|
||||
fcm_cycles_time, /* evaluate time */
|
||||
fcm_cycles_evaluate /* evaluate */
|
||||
};
|
||||
|
||||
/* Noise F-Curve Modifier --------------------------- */
|
||||
|
||||
static void fcm_noise_new_data (void *mdata)
|
||||
{
|
||||
FMod_Noise *data= (FMod_Noise *)mdata;
|
||||
|
||||
/* defaults */
|
||||
data->size= 1.0f;
|
||||
data->strength= 1.0f;
|
||||
data->phase= 1.0f;
|
||||
data->depth = 0;
|
||||
data->modification = FCM_NOISE_MODIF_REPLACE;
|
||||
}
|
||||
|
||||
static void fcm_noise_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
|
||||
{
|
||||
FMod_Noise *data= (FMod_Noise *)fcm->data;
|
||||
float noise;
|
||||
|
||||
noise = BLI_turbulence(data->size, evaltime, data->phase, 0.f, data->depth);
|
||||
|
||||
switch (data->modification) {
|
||||
case FCM_NOISE_MODIF_ADD:
|
||||
*cvalue= *cvalue + noise * data->strength;
|
||||
break;
|
||||
case FCM_NOISE_MODIF_SUBTRACT:
|
||||
*cvalue= *cvalue - noise * data->strength;
|
||||
break;
|
||||
case FCM_NOISE_MODIF_MULTIPLY:
|
||||
*cvalue= *cvalue * noise * data->strength;
|
||||
break;
|
||||
case FCM_NOISE_MODIF_REPLACE:
|
||||
default:
|
||||
*cvalue= *cvalue + (noise - 0.5f) * data->strength;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static FModifierTypeInfo FMI_NOISE = {
|
||||
FMODIFIER_TYPE_NOISE, /* type */
|
||||
sizeof(FMod_Noise), /* size */
|
||||
FMI_TYPE_REPLACE_VALUES, /* action type */
|
||||
0, /* requirements */
|
||||
"Noise", /* name */
|
||||
"FMod_Noise", /* struct name */
|
||||
NULL, /* free data */
|
||||
NULL, /* copy data */
|
||||
fcm_noise_new_data, /* new data */
|
||||
NULL /*fcm_noise_verify*/, /* verify */
|
||||
NULL, /* evaluate time */
|
||||
fcm_noise_evaluate /* evaluate */
|
||||
};
|
||||
|
||||
/* Filter F-Curve Modifier --------------------------- */
|
||||
|
||||
#if 0 // XXX not yet implemented
|
||||
static FModifierTypeInfo FMI_FILTER = {
|
||||
FMODIFIER_TYPE_FILTER, /* type */
|
||||
sizeof(FMod_Filter), /* size */
|
||||
FMI_TYPE_REPLACE_VALUES, /* action type */
|
||||
0, /* requirements */
|
||||
"Filter", /* name */
|
||||
"FMod_Filter", /* struct name */
|
||||
NULL, /* free data */
|
||||
NULL, /* copy data */
|
||||
NULL, /* new data */
|
||||
NULL /*fcm_filter_verify*/, /* verify */
|
||||
NULL, /* evlauate time */
|
||||
fcm_filter_evaluate /* evaluate */
|
||||
};
|
||||
#endif // XXX not yet implemented
|
||||
|
||||
|
||||
/* Python F-Curve Modifier --------------------------- */
|
||||
|
||||
static void fcm_python_free (FModifier *fcm)
|
||||
{
|
||||
FMod_Python *data= (FMod_Python *)fcm->data;
|
||||
|
||||
/* id-properties */
|
||||
IDP_FreeProperty(data->prop);
|
||||
MEM_freeN(data->prop);
|
||||
}
|
||||
|
||||
static void fcm_python_new_data (void *mdata)
|
||||
{
|
||||
FMod_Python *data= (FMod_Python *)mdata;
|
||||
|
||||
/* everything should be set correctly by calloc, except for the prop->type constant.*/
|
||||
data->prop = MEM_callocN(sizeof(IDProperty), "PyFModifierProps");
|
||||
data->prop->type = IDP_GROUP;
|
||||
}
|
||||
|
||||
static void fcm_python_copy (FModifier *fcm, FModifier *src)
|
||||
{
|
||||
FMod_Python *pymod = (FMod_Python *)fcm->data;
|
||||
FMod_Python *opymod = (FMod_Python *)src->data;
|
||||
|
||||
pymod->prop = IDP_CopyProperty(opymod->prop);
|
||||
}
|
||||
|
||||
static void fcm_python_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
|
||||
{
|
||||
#ifndef DISABLE_PYTHON
|
||||
//FMod_Python *data= (FMod_Python *)fcm->data;
|
||||
|
||||
/* FIXME... need to implement this modifier...
|
||||
* It will need it execute a script using the custom properties
|
||||
*/
|
||||
#endif /* DISABLE_PYTHON */
|
||||
}
|
||||
|
||||
static FModifierTypeInfo FMI_PYTHON = {
|
||||
FMODIFIER_TYPE_PYTHON, /* type */
|
||||
sizeof(FMod_Python), /* size */
|
||||
FMI_TYPE_GENERATE_CURVE, /* action type */
|
||||
FMI_REQUIRES_RUNTIME_CHECK, /* requirements */
|
||||
"Python", /* name */
|
||||
"FMod_Python", /* struct name */
|
||||
fcm_python_free, /* free data */
|
||||
fcm_python_copy, /* copy data */
|
||||
fcm_python_new_data, /* new data */
|
||||
NULL /*fcm_python_verify*/, /* verify */
|
||||
NULL /*fcm_python_time*/, /* evaluate time */
|
||||
fcm_python_evaluate /* evaluate */
|
||||
};
|
||||
|
||||
|
||||
/* Limits F-Curve Modifier --------------------------- */
|
||||
|
||||
static float fcm_limits_time (FCurve *fcu, FModifier *fcm, float cvalue, float evaltime)
|
||||
{
|
||||
FMod_Limits *data= (FMod_Limits *)fcm->data;
|
||||
|
||||
/* check for the time limits */
|
||||
if ((data->flag & FCM_LIMIT_XMIN) && (evaltime < data->rect.xmin))
|
||||
return data->rect.xmin;
|
||||
if ((data->flag & FCM_LIMIT_XMAX) && (evaltime > data->rect.xmax))
|
||||
return data->rect.xmax;
|
||||
|
||||
/* modifier doesn't change time */
|
||||
return evaltime;
|
||||
}
|
||||
|
||||
static void fcm_limits_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
|
||||
{
|
||||
FMod_Limits *data= (FMod_Limits *)fcm->data;
|
||||
|
||||
/* value limits now */
|
||||
if ((data->flag & FCM_LIMIT_YMIN) && (*cvalue < data->rect.ymin))
|
||||
*cvalue= data->rect.ymin;
|
||||
if ((data->flag & FCM_LIMIT_YMAX) && (*cvalue > data->rect.ymax))
|
||||
*cvalue= data->rect.ymax;
|
||||
}
|
||||
|
||||
static FModifierTypeInfo FMI_LIMITS = {
|
||||
FMODIFIER_TYPE_LIMITS, /* type */
|
||||
sizeof(FMod_Limits), /* size */
|
||||
FMI_TYPE_GENERATE_CURVE, /* action type */ /* XXX... err... */
|
||||
FMI_REQUIRES_RUNTIME_CHECK, /* requirements */
|
||||
"Limits", /* name */
|
||||
"FMod_Limits", /* struct name */
|
||||
NULL, /* free data */
|
||||
NULL, /* copy data */
|
||||
NULL, /* new data */
|
||||
NULL, /* verify */
|
||||
fcm_limits_time, /* evaluate time */
|
||||
fcm_limits_evaluate /* evaluate */
|
||||
};
|
||||
|
||||
/* F-Curve Modifier API --------------------------- */
|
||||
/* All of the F-Curve Modifier api functions use FModifierTypeInfo structs to carry out
|
||||
* and operations that involve F-Curve modifier specific code.
|
||||
*/
|
||||
|
||||
/* These globals only ever get directly accessed in this file */
|
||||
static FModifierTypeInfo *fmodifiersTypeInfo[FMODIFIER_NUM_TYPES];
|
||||
static short FMI_INIT= 1; /* when non-zero, the list needs to be updated */
|
||||
|
||||
/* This function only gets called when FMI_INIT is non-zero */
|
||||
static void fmods_init_typeinfo ()
|
||||
{
|
||||
fmodifiersTypeInfo[0]= NULL; /* 'Null' F-Curve Modifier */
|
||||
fmodifiersTypeInfo[1]= &FMI_GENERATOR; /* Generator F-Curve Modifier */
|
||||
fmodifiersTypeInfo[2]= &FMI_ENVELOPE; /* Envelope F-Curve Modifier */
|
||||
fmodifiersTypeInfo[3]= &FMI_CYCLES; /* Cycles F-Curve Modifier */
|
||||
fmodifiersTypeInfo[4]= &FMI_NOISE; /* Apply-Noise F-Curve Modifier */
|
||||
fmodifiersTypeInfo[5]= NULL/*&FMI_FILTER*/; /* Filter F-Curve Modifier */ // XXX unimplemented
|
||||
fmodifiersTypeInfo[6]= &FMI_PYTHON; /* Custom Python F-Curve Modifier */
|
||||
fmodifiersTypeInfo[7]= &FMI_LIMITS; /* Limits F-Curve Modifier */
|
||||
}
|
||||
|
||||
/* This function should be used for getting the appropriate type-info when only
|
||||
* a F-Curve modifier type is known
|
||||
*/
|
||||
FModifierTypeInfo *get_fmodifier_typeinfo (int type)
|
||||
{
|
||||
/* initialise the type-info list? */
|
||||
if (FMI_INIT) {
|
||||
fmods_init_typeinfo();
|
||||
FMI_INIT = 0;
|
||||
}
|
||||
|
||||
/* only return for valid types */
|
||||
if ( (type >= FMODIFIER_TYPE_NULL) &&
|
||||
(type <= FMODIFIER_NUM_TYPES ) )
|
||||
{
|
||||
/* there shouldn't be any segfaults here... */
|
||||
return fmodifiersTypeInfo[type];
|
||||
}
|
||||
else {
|
||||
printf("No valid F-Curve Modifier type-info data available. Type = %i \n", type);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* This function should always be used to get the appropriate type-info, as it
|
||||
* has checks which prevent segfaults in some weird cases.
|
||||
*/
|
||||
FModifierTypeInfo *fmodifier_get_typeinfo (FModifier *fcm)
|
||||
{
|
||||
/* only return typeinfo for valid modifiers */
|
||||
if (fcm)
|
||||
return get_fmodifier_typeinfo(fcm->type);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* API --------------------------- */
|
||||
|
||||
/* Add a new F-Curve Modifier to the given F-Curve of a certain type */
|
||||
FModifier *fcurve_add_modifier (FCurve *fcu, int type)
|
||||
{
|
||||
FModifierTypeInfo *fmi= get_fmodifier_typeinfo(type);
|
||||
FModifier *fcm;
|
||||
|
||||
/* sanity checks */
|
||||
if ELEM(NULL, fcu, fmi)
|
||||
return NULL;
|
||||
|
||||
/* special checks for whether modifier can be added */
|
||||
if ((fcu->modifiers.first) && (type == FMODIFIER_TYPE_CYCLES)) {
|
||||
/* cycles modifier must be first in stack, so for now, don't add if it can't be */
|
||||
// TODO: perhaps there is some better way, but for now,
|
||||
printf("Error: Cannot add 'Cycles' modifier to F-Curve, as 'Cycles' modifier can only be first in stack. \n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* add modifier itself */
|
||||
fcm= MEM_callocN(sizeof(FModifier), "F-Curve Modifier");
|
||||
fcm->type = type;
|
||||
fcm->flag = FMODIFIER_FLAG_EXPANDED;
|
||||
BLI_addtail(&fcu->modifiers, fcm);
|
||||
|
||||
/* add modifier's data */
|
||||
fcm->data= MEM_callocN(fmi->size, fmi->structName);
|
||||
|
||||
/* init custom settings if necessary */
|
||||
if (fmi->new_data)
|
||||
fmi->new_data(fcm->data);
|
||||
|
||||
/* return modifier for further editing */
|
||||
return fcm;
|
||||
}
|
||||
|
||||
/* Duplicate all of the F-Curve Modifiers in the Modifier stacks */
|
||||
void fcurve_copy_modifiers (ListBase *dst, ListBase *src)
|
||||
{
|
||||
FModifier *fcm, *srcfcm;
|
||||
|
||||
if ELEM(NULL, dst, src)
|
||||
return;
|
||||
|
||||
dst->first= dst->last= NULL;
|
||||
BLI_duplicatelist(dst, src);
|
||||
|
||||
for (fcm=dst->first, srcfcm=src->first; fcm && srcfcm; srcfcm=srcfcm->next, fcm=fcm->next) {
|
||||
FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
|
||||
|
||||
/* make a new copy of the F-Modifier's data */
|
||||
fcm->data = MEM_dupallocN(fcm->data);
|
||||
|
||||
/* only do specific constraints if required */
|
||||
if (fmi && fmi->copy_data)
|
||||
fmi->copy_data(fcm, srcfcm);
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove and free the given F-Curve Modifier from the given F-Curve's stack */
|
||||
void fcurve_remove_modifier (FCurve *fcu, FModifier *fcm)
|
||||
{
|
||||
FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
|
||||
|
||||
/* sanity check */
|
||||
if (fcm == NULL)
|
||||
return;
|
||||
|
||||
/* free modifier's special data (stored inside fcm->data) */
|
||||
if (fcm->data) {
|
||||
if (fmi && fmi->free_data)
|
||||
fmi->free_data(fcm);
|
||||
|
||||
/* free modifier's data (fcm->data) */
|
||||
MEM_freeN(fcm->data);
|
||||
}
|
||||
|
||||
/* remove modifier from stack */
|
||||
if (fcu)
|
||||
BLI_freelinkN(&fcu->modifiers, fcm);
|
||||
else {
|
||||
// XXX this case can probably be removed some day, as it shouldn't happen...
|
||||
printf("fcurve_remove_modifier() - no fcurve \n");
|
||||
MEM_freeN(fcm);
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove all of a given F-Curve's modifiers */
|
||||
void fcurve_free_modifiers (FCurve *fcu)
|
||||
{
|
||||
FModifier *fcm, *fmn;
|
||||
|
||||
/* sanity check */
|
||||
if (fcu == NULL)
|
||||
return;
|
||||
|
||||
/* free each modifier in order - modifier is unlinked from list and freed */
|
||||
for (fcm= fcu->modifiers.first; fcm; fcm= fmn) {
|
||||
fmn= fcm->next;
|
||||
fcurve_remove_modifier(fcu, fcm);
|
||||
}
|
||||
}
|
||||
|
||||
/* Bake modifiers for given F-Curve to curve sample data, in the frame range defined
|
||||
* by start and end (inclusive).
|
||||
*/
|
||||
void fcurve_bake_modifiers (FCurve *fcu, int start, int end)
|
||||
{
|
||||
ChannelDriver *driver;
|
||||
|
||||
/* sanity checks */
|
||||
// TODO: make these tests report errors using reports not printf's
|
||||
if ELEM(NULL, fcu, fcu->modifiers.first) {
|
||||
printf("Error: No F-Curve with F-Curve Modifiers to Bake\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* temporarily, disable driver while we sample, so that they don't influence the outcome */
|
||||
driver= fcu->driver;
|
||||
fcu->driver= NULL;
|
||||
|
||||
/* bake the modifiers, by sampling the curve at each frame */
|
||||
fcurve_store_samples(fcu, NULL, start, end, fcurve_samplingcb_evalcurve);
|
||||
|
||||
/* free the modifiers now */
|
||||
fcurve_free_modifiers(fcu);
|
||||
|
||||
/* restore driver */
|
||||
fcu->driver= driver;
|
||||
}
|
||||
|
||||
/* Find the active F-Curve Modifier */
|
||||
FModifier *fcurve_find_active_modifier (FCurve *fcu)
|
||||
{
|
||||
FModifier *fcm;
|
||||
|
||||
/* sanity checks */
|
||||
if ELEM(NULL, fcu, fcu->modifiers.first)
|
||||
return NULL;
|
||||
|
||||
/* loop over modifiers until 'active' one is found */
|
||||
for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next) {
|
||||
if (fcm->flag & FMODIFIER_FLAG_ACTIVE)
|
||||
return fcm;
|
||||
}
|
||||
|
||||
/* no modifier is active */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Set the active F-Curve Modifier */
|
||||
void fcurve_set_active_modifier (FCurve *fcu, FModifier *fcm)
|
||||
{
|
||||
FModifier *fm;
|
||||
|
||||
/* sanity checks */
|
||||
if ELEM(NULL, fcu, fcu->modifiers.first)
|
||||
return;
|
||||
|
||||
/* deactivate all, and set current one active */
|
||||
for (fm= fcu->modifiers.first; fm; fm= fm->next)
|
||||
fm->flag &= ~FMODIFIER_FLAG_ACTIVE;
|
||||
|
||||
/* make given modifier active */
|
||||
if (fcm)
|
||||
fcm->flag |= FMODIFIER_FLAG_ACTIVE;
|
||||
}
|
||||
|
||||
/* ***************************** F-Curve - Evaluation ********************************* */
|
||||
|
||||
/* Evaluate and return the value of the given F-Curve at the specified frame ("evaltime")
|
||||
@@ -2262,7 +1263,6 @@ void fcurve_set_active_modifier (FCurve *fcu, FModifier *fcm)
|
||||
*/
|
||||
float evaluate_fcurve (FCurve *fcu, float evaltime)
|
||||
{
|
||||
FModifier *fcm;
|
||||
float cvalue= 0.0f;
|
||||
float devaltime;
|
||||
|
||||
@@ -2275,28 +1275,8 @@ float evaluate_fcurve (FCurve *fcu, float evaltime)
|
||||
evaltime= cvalue= evaluate_driver(fcu->driver, evaltime);
|
||||
}
|
||||
|
||||
/* evaluate time modifications imposed by some F-Curve Modifiers
|
||||
* - this step acts as an optimisation to prevent the F-Curve stack being evaluated
|
||||
* several times by modifiers requesting the time be modified, as the final result
|
||||
* would have required using the modified time
|
||||
* - modifiers only ever recieve the unmodified time, as subsequent modifiers should be
|
||||
* working on the 'global' result of the modified curve, not some localised segment,
|
||||
* so nevaltime gets set to whatever the last time-modifying modifier likes...
|
||||
* - we start from the end of the stack, as only the last one matters for now
|
||||
*/
|
||||
devaltime= evaltime;
|
||||
|
||||
for (fcm= fcu->modifiers.last; fcm; fcm= fcm->prev) {
|
||||
FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
|
||||
|
||||
/* only evaluate if there's a callback for this */
|
||||
// TODO: implement the 'influence' control feature...
|
||||
if (fmi && fmi->evaluate_modifier_time) {
|
||||
if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0)
|
||||
devaltime= fmi->evaluate_modifier_time(fcu, fcm, cvalue, evaltime);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* evaluate modifiers which modify time to evaluate the base curve at */
|
||||
devaltime= evaluate_time_fmodifiers(&fcu->modifiers, fcu, cvalue, evaltime);
|
||||
|
||||
/* evaluate curve-data
|
||||
* - 'devaltime' instead of 'evaltime', as this is the time that the last time-modifying
|
||||
@@ -2308,16 +1288,7 @@ float evaluate_fcurve (FCurve *fcu, float evaltime)
|
||||
cvalue= fcurve_eval_samples(fcu, fcu->fpt, devaltime);
|
||||
|
||||
/* evaluate modifiers */
|
||||
for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next) {
|
||||
FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
|
||||
|
||||
/* only evaluate if there's a callback for this */
|
||||
// TODO: implement the 'influence' control feature...
|
||||
if (fmi && fmi->evaluate_modifier) {
|
||||
if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0)
|
||||
fmi->evaluate_modifier(fcu, fcm, &cvalue, evaltime);
|
||||
}
|
||||
}
|
||||
evaluate_value_fmodifiers(&fcu->modifiers, fcu, &cvalue, evaltime);
|
||||
|
||||
/* if curve can only have integral values, perform truncation (i.e. drop the decimal part)
|
||||
* here so that the curve can be sampled correctly
|
||||
@@ -2330,10 +1301,16 @@ float evaluate_fcurve (FCurve *fcu, float evaltime)
|
||||
}
|
||||
|
||||
/* Calculate the value of the given F-Curve at the given frame, and set its curval */
|
||||
// TODO: will this be necessary?
|
||||
void calculate_fcurve (FCurve *fcu, float ctime)
|
||||
{
|
||||
/* calculate and set curval (evaluates driver too) */
|
||||
fcu->curval= evaluate_fcurve(fcu, ctime);
|
||||
/* only calculate + set curval (overriding the existing value) if curve has
|
||||
* any data which warrants this...
|
||||
*/
|
||||
if ( (fcu->totvert) || (fcu->driver && !(fcu->driver->flag & DRIVER_FLAG_INVALID)) ||
|
||||
list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) )
|
||||
{
|
||||
/* calculate and set curval (evaluates driver too if necessary) */
|
||||
fcu->curval= evaluate_fcurve(fcu, ctime);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
1197
source/blender/blenkernel/intern/fmodifier.c
Normal file
1197
source/blender/blenkernel/intern/fmodifier.c
Normal file
@@ -0,0 +1,1197 @@
|
||||
/**
|
||||
* $Id: fcurve.c 21299 2009-07-02 02:12:37Z aligorith $
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
|
||||
* All rights reserved.
|
||||
*
|
||||
* Contributor(s): Joshua Leung (full recode)
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <float.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "DNA_anim_types.h"
|
||||
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_arithb.h"
|
||||
#include "BLI_noise.h"
|
||||
|
||||
#include "BKE_fcurve.h"
|
||||
#include "BKE_curve.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_utildefines.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_types.h"
|
||||
|
||||
#ifndef DISABLE_PYTHON
|
||||
#include "BPY_extern.h" /* for BPY_pydriver_eval() */
|
||||
#endif
|
||||
|
||||
#define SMALL -1.0e-10
|
||||
#define SELECT 1
|
||||
|
||||
/* ******************************** F-Modifiers ********************************* */
|
||||
|
||||
/* Info ------------------------------- */
|
||||
|
||||
/* F-Modifiers are modifiers which operate on F-Curves. However, they can also be defined
|
||||
* on NLA-Strips to affect all of the F-Curves referenced by the NLA-Strip.
|
||||
*/
|
||||
|
||||
/* Template --------------------------- */
|
||||
|
||||
/* Each modifier defines a set of functions, which will be called at the appropriate
|
||||
* times. In addition to this, each modifier should have a type-info struct, where
|
||||
* its functions are attached for use.
|
||||
*/
|
||||
|
||||
/* Template for type-info data:
|
||||
* - make a copy of this when creating new modifiers, and just change the functions
|
||||
* pointed to as necessary
|
||||
* - although the naming of functions doesn't matter, it would help for code
|
||||
* readability, to follow the same naming convention as is presented here
|
||||
* - any functions that a constraint doesn't need to define, don't define
|
||||
* for such cases, just use NULL
|
||||
* - these should be defined after all the functions have been defined, so that
|
||||
* forward-definitions/prototypes don't need to be used!
|
||||
* - keep this copy #if-def'd so that future constraints can get based off this
|
||||
*/
|
||||
#if 0
|
||||
static FModifierTypeInfo FMI_MODNAME = {
|
||||
FMODIFIER_TYPE_MODNAME, /* type */
|
||||
sizeof(FMod_ModName), /* size */
|
||||
FMI_TYPE_SOME_ACTION, /* action type */
|
||||
FMI_REQUIRES_SOME_REQUIREMENT, /* requirements */
|
||||
"Modifier Name", /* name */
|
||||
"FMod_ModName", /* struct name */
|
||||
fcm_modname_free, /* free data */
|
||||
fcm_modname_relink, /* relink data */
|
||||
fcm_modname_copy, /* copy data */
|
||||
fcm_modname_new_data, /* new data */
|
||||
fcm_modname_verify, /* verify */
|
||||
fcm_modname_time, /* evaluate time */
|
||||
fcm_modname_evaluate /* evaluate */
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Generator F-Curve Modifier --------------------------- */
|
||||
|
||||
/* Generators available:
|
||||
* 1) simple polynomial generator:
|
||||
* - Exanded form - (y = C[0]*(x^(n)) + C[1]*(x^(n-1)) + ... + C[n])
|
||||
* - Factorised form - (y = (C[0][0]*x + C[0][1]) * (C[1][0]*x + C[1][1]) * ... * (C[n][0]*x + C[n][1]))
|
||||
*/
|
||||
|
||||
static void fcm_generator_free (FModifier *fcm)
|
||||
{
|
||||
FMod_Generator *data= (FMod_Generator *)fcm->data;
|
||||
|
||||
/* free polynomial coefficients array */
|
||||
if (data->coefficients)
|
||||
MEM_freeN(data->coefficients);
|
||||
}
|
||||
|
||||
static void fcm_generator_copy (FModifier *fcm, FModifier *src)
|
||||
{
|
||||
FMod_Generator *gen= (FMod_Generator *)fcm->data;
|
||||
FMod_Generator *ogen= (FMod_Generator *)src->data;
|
||||
|
||||
/* copy coefficients array? */
|
||||
if (ogen->coefficients)
|
||||
gen->coefficients= MEM_dupallocN(ogen->coefficients);
|
||||
}
|
||||
|
||||
static void fcm_generator_new_data (void *mdata)
|
||||
{
|
||||
FMod_Generator *data= (FMod_Generator *)mdata;
|
||||
float *cp;
|
||||
|
||||
/* set default generator to be linear 0-1 (gradient = 1, y-offset = 0) */
|
||||
data->poly_order= 1;
|
||||
data->arraysize= 2;
|
||||
cp= data->coefficients= MEM_callocN(sizeof(float)*2, "FMod_Generator_Coefs");
|
||||
cp[0] = 0; // y-offset
|
||||
cp[1] = 1; // gradient
|
||||
}
|
||||
|
||||
static void fcm_generator_verify (FModifier *fcm)
|
||||
{
|
||||
FMod_Generator *data= (FMod_Generator *)fcm->data;
|
||||
|
||||
/* requirements depend on mode */
|
||||
switch (data->mode) {
|
||||
case FCM_GENERATOR_POLYNOMIAL: /* expanded polynomial expression */
|
||||
{
|
||||
/* arraysize needs to be order+1, so resize if not */
|
||||
if (data->arraysize != (data->poly_order+1)) {
|
||||
float *nc;
|
||||
|
||||
/* make new coefficients array, and copy over as much data as can fit */
|
||||
nc= MEM_callocN(sizeof(float)*(data->poly_order+1), "FMod_Generator_Coefs");
|
||||
|
||||
if (data->coefficients) {
|
||||
if (data->arraysize > (data->poly_order+1))
|
||||
memcpy(nc, data->coefficients, sizeof(float)*(data->poly_order+1));
|
||||
else
|
||||
memcpy(nc, data->coefficients, sizeof(float)*data->arraysize);
|
||||
|
||||
/* free the old data */
|
||||
MEM_freeN(data->coefficients);
|
||||
}
|
||||
|
||||
/* set the new data */
|
||||
data->coefficients= nc;
|
||||
data->arraysize= data->poly_order+1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* expanded polynomial expression */
|
||||
{
|
||||
/* arraysize needs to be 2*order, so resize if not */
|
||||
if (data->arraysize != (data->poly_order * 2)) {
|
||||
float *nc;
|
||||
|
||||
/* make new coefficients array, and copy over as much data as can fit */
|
||||
nc= MEM_callocN(sizeof(float)*(data->poly_order*2), "FMod_Generator_Coefs");
|
||||
|
||||
if (data->coefficients) {
|
||||
if (data->arraysize > (data->poly_order * 2))
|
||||
memcpy(nc, data->coefficients, sizeof(float)*(data->poly_order * 2));
|
||||
else
|
||||
memcpy(nc, data->coefficients, sizeof(float)*data->arraysize);
|
||||
|
||||
/* free the old data */
|
||||
MEM_freeN(data->coefficients);
|
||||
}
|
||||
|
||||
/* set the new data */
|
||||
data->coefficients= nc;
|
||||
data->arraysize= data->poly_order * 2;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void fcm_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
|
||||
{
|
||||
FMod_Generator *data= (FMod_Generator *)fcm->data;
|
||||
|
||||
/* behaviour depends on mode
|
||||
* NOTE: the data in its default state is fine too
|
||||
*/
|
||||
switch (data->mode) {
|
||||
case FCM_GENERATOR_POLYNOMIAL: /* expanded polynomial expression */
|
||||
{
|
||||
/* we overwrite cvalue with the sum of the polynomial */
|
||||
float *powers = MEM_callocN(sizeof(float)*data->arraysize, "Poly Powers");
|
||||
float value= 0.0f;
|
||||
unsigned int i;
|
||||
|
||||
/* for each x^n, precalculate value based on previous one first... this should be
|
||||
* faster that calling pow() for each entry
|
||||
*/
|
||||
for (i=0; i < data->arraysize; i++) {
|
||||
/* first entry is x^0 = 1, otherwise, calculate based on previous */
|
||||
if (i)
|
||||
powers[i]= powers[i-1] * evaltime;
|
||||
else
|
||||
powers[0]= 1;
|
||||
}
|
||||
|
||||
/* for each coefficient, add to value, which we'll write to *cvalue in one go */
|
||||
for (i=0; i < data->arraysize; i++)
|
||||
value += data->coefficients[i] * powers[i];
|
||||
|
||||
/* only if something changed, write *cvalue in one go */
|
||||
if (data->poly_order) {
|
||||
if (data->flag & FCM_GENERATOR_ADDITIVE)
|
||||
*cvalue += value;
|
||||
else
|
||||
*cvalue= value;
|
||||
}
|
||||
|
||||
/* cleanup */
|
||||
if (powers)
|
||||
MEM_freeN(powers);
|
||||
}
|
||||
break;
|
||||
|
||||
case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* factorised polynomial */
|
||||
{
|
||||
float value= 1.0f, *cp=NULL;
|
||||
unsigned int i;
|
||||
|
||||
/* for each coefficient pair, solve for that bracket before accumulating in value by multiplying */
|
||||
for (cp=data->coefficients, i=0; (cp) && (i < data->poly_order); cp+=2, i++)
|
||||
value *= (cp[0]*evaltime + cp[1]);
|
||||
|
||||
/* only if something changed, write *cvalue in one go */
|
||||
if (data->poly_order) {
|
||||
if (data->flag & FCM_GENERATOR_ADDITIVE)
|
||||
*cvalue += value;
|
||||
else
|
||||
*cvalue= value;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static FModifierTypeInfo FMI_GENERATOR = {
|
||||
FMODIFIER_TYPE_GENERATOR, /* type */
|
||||
sizeof(FMod_Generator), /* size */
|
||||
FMI_TYPE_GENERATE_CURVE, /* action type */
|
||||
FMI_REQUIRES_NOTHING, /* requirements */
|
||||
"Generator", /* name */
|
||||
"FMod_Generator", /* struct name */
|
||||
fcm_generator_free, /* free data */
|
||||
fcm_generator_copy, /* copy data */
|
||||
fcm_generator_new_data, /* new data */
|
||||
fcm_generator_verify, /* verify */
|
||||
NULL, /* evaluate time */
|
||||
fcm_generator_evaluate /* evaluate */
|
||||
};
|
||||
|
||||
/* Built-In Function Generator F-Curve Modifier --------------------------- */
|
||||
|
||||
/* This uses the general equation for equations:
|
||||
* y = amplitude * fn(phase_multiplier*x + phase_offset) + y_offset
|
||||
*
|
||||
* where amplitude, phase_multiplier/offset, y_offset are user-defined coefficients,
|
||||
* x is the evaluation 'time', and 'y' is the resultant value
|
||||
*
|
||||
* Functions available are
|
||||
* sin, cos, tan, sinc (normalised sin), natural log, square root
|
||||
*/
|
||||
|
||||
static void fcm_fn_generator_new_data (void *mdata)
|
||||
{
|
||||
FMod_FunctionGenerator *data= (FMod_FunctionGenerator *)mdata;
|
||||
|
||||
/* set amplitude and phase multiplier to 1.0f so that something is generated */
|
||||
data->amplitude= 1.0f;
|
||||
data->phase_multiplier= 1.0f;
|
||||
}
|
||||
|
||||
/* Unary 'normalised sine' function
|
||||
* y = sin(PI + x) / (PI * x),
|
||||
* except for x = 0 when y = 1.
|
||||
*/
|
||||
static double sinc (double x)
|
||||
{
|
||||
if (fabs(x) < 0.0001)
|
||||
return 1.0;
|
||||
else
|
||||
return sin(M_PI * x) / (M_PI * x);
|
||||
}
|
||||
|
||||
static void fcm_fn_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
|
||||
{
|
||||
FMod_FunctionGenerator *data= (FMod_FunctionGenerator *)fcm->data;
|
||||
double arg= data->phase_multiplier*evaltime + data->phase_offset;
|
||||
double (*fn)(double v) = NULL;
|
||||
|
||||
/* get function pointer to the func to use:
|
||||
* WARNING: must perform special argument validation hereto guard against crashes
|
||||
*/
|
||||
switch (data->type)
|
||||
{
|
||||
/* simple ones */
|
||||
case FCM_GENERATOR_FN_SIN: /* sine wave */
|
||||
fn= sin;
|
||||
break;
|
||||
case FCM_GENERATOR_FN_COS: /* cosine wave */
|
||||
fn= cos;
|
||||
break;
|
||||
case FCM_GENERATOR_FN_SINC: /* normalised sine wave */
|
||||
fn= sinc;
|
||||
break;
|
||||
|
||||
/* validation required */
|
||||
case FCM_GENERATOR_FN_TAN: /* tangent wave */
|
||||
{
|
||||
/* check that argument is not on one of the discontinuities (i.e. 90deg, 270 deg, etc) */
|
||||
if IS_EQ(fmod((arg - M_PI_2), M_PI), 0.0) {
|
||||
if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0)
|
||||
*cvalue = 0.0f; /* no value possible here */
|
||||
}
|
||||
else
|
||||
fn= tan;
|
||||
}
|
||||
break;
|
||||
case FCM_GENERATOR_FN_LN: /* natural log */
|
||||
{
|
||||
/* check that value is greater than 1? */
|
||||
if (arg > 1.0f) {
|
||||
fn= log;
|
||||
}
|
||||
else {
|
||||
if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0)
|
||||
*cvalue = 0.0f; /* no value possible here */
|
||||
}
|
||||
}
|
||||
break;
|
||||
case FCM_GENERATOR_FN_SQRT: /* square root */
|
||||
{
|
||||
/* no negative numbers */
|
||||
if (arg > 0.0f) {
|
||||
fn= sqrt;
|
||||
}
|
||||
else {
|
||||
if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0)
|
||||
*cvalue = 0.0f; /* no value possible here */
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("Invalid Function-Generator for F-Modifier - %d \n", data->type);
|
||||
}
|
||||
|
||||
/* execute function callback to set value if appropriate */
|
||||
if (fn) {
|
||||
float value= (float)(data->amplitude*fn(arg) + data->value_offset);
|
||||
|
||||
if (data->flag & FCM_GENERATOR_ADDITIVE)
|
||||
*cvalue += value;
|
||||
else
|
||||
*cvalue= value;
|
||||
}
|
||||
}
|
||||
|
||||
static FModifierTypeInfo FMI_FN_GENERATOR = {
|
||||
FMODIFIER_TYPE_FN_GENERATOR, /* type */
|
||||
sizeof(FMod_FunctionGenerator), /* size */
|
||||
FMI_TYPE_GENERATE_CURVE, /* action type */
|
||||
FMI_REQUIRES_NOTHING, /* requirements */
|
||||
"Built-In Function", /* name */
|
||||
"FMod_FunctionGenerator", /* struct name */
|
||||
NULL, /* free data */
|
||||
NULL, /* copy data */
|
||||
fcm_fn_generator_new_data, /* new data */
|
||||
NULL, /* verify */
|
||||
NULL, /* evaluate time */
|
||||
fcm_fn_generator_evaluate /* evaluate */
|
||||
};
|
||||
|
||||
/* Envelope F-Curve Modifier --------------------------- */
|
||||
|
||||
static void fcm_envelope_free (FModifier *fcm)
|
||||
{
|
||||
FMod_Envelope *env= (FMod_Envelope *)fcm->data;
|
||||
|
||||
/* free envelope data array */
|
||||
if (env->data)
|
||||
MEM_freeN(env->data);
|
||||
}
|
||||
|
||||
static void fcm_envelope_copy (FModifier *fcm, FModifier *src)
|
||||
{
|
||||
FMod_Envelope *env= (FMod_Envelope *)fcm->data;
|
||||
FMod_Envelope *oenv= (FMod_Envelope *)src->data;
|
||||
|
||||
/* copy envelope data array */
|
||||
if (oenv->data)
|
||||
env->data= MEM_dupallocN(oenv->data);
|
||||
}
|
||||
|
||||
static void fcm_envelope_new_data (void *mdata)
|
||||
{
|
||||
FMod_Envelope *env= (FMod_Envelope *)mdata;
|
||||
|
||||
/* set default min/max ranges */
|
||||
env->min= -1.0f;
|
||||
env->max= 1.0f;
|
||||
}
|
||||
|
||||
static void fcm_envelope_verify (FModifier *fcm)
|
||||
{
|
||||
FMod_Envelope *env= (FMod_Envelope *)fcm->data;
|
||||
|
||||
/* if the are points, perform bubble-sort on them, as user may have changed the order */
|
||||
if (env->data) {
|
||||
// XXX todo...
|
||||
}
|
||||
}
|
||||
|
||||
static void fcm_envelope_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
|
||||
{
|
||||
FMod_Envelope *env= (FMod_Envelope *)fcm->data;
|
||||
FCM_EnvelopeData *fed, *prevfed, *lastfed;
|
||||
float min=0.0f, max=0.0f, fac=0.0f;
|
||||
int a;
|
||||
|
||||
/* get pointers */
|
||||
if (env->data == NULL) return;
|
||||
prevfed= env->data;
|
||||
fed= prevfed + 1;
|
||||
lastfed= prevfed + (env->totvert-1);
|
||||
|
||||
/* get min/max values for envelope at evaluation time (relative to mid-value) */
|
||||
if (prevfed->time >= evaltime) {
|
||||
/* before or on first sample, so just extend value */
|
||||
min= prevfed->min;
|
||||
max= prevfed->max;
|
||||
}
|
||||
else if (lastfed->time <= evaltime) {
|
||||
/* after or on last sample, so just extend value */
|
||||
min= lastfed->min;
|
||||
max= lastfed->max;
|
||||
}
|
||||
else {
|
||||
/* evaltime occurs somewhere between segments */
|
||||
// TODO: implement binary search for this to make it faster?
|
||||
for (a=0; prevfed && fed && (a < env->totvert-1); a++, prevfed=fed, fed++) {
|
||||
/* evaltime occurs within the interval defined by these two envelope points */
|
||||
if ((prevfed->time <= evaltime) && (fed->time >= evaltime)) {
|
||||
float afac, bfac, diff;
|
||||
|
||||
diff= fed->time - prevfed->time;
|
||||
afac= (evaltime - prevfed->time) / diff;
|
||||
bfac= (fed->time - evaltime) / diff;
|
||||
|
||||
min= bfac*prevfed->min + afac*fed->min;
|
||||
max= bfac*prevfed->max + afac*fed->max;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* adjust *cvalue
|
||||
* - fac is the ratio of how the current y-value corresponds to the reference range
|
||||
* - thus, the new value is found by mapping the old range to the new!
|
||||
*/
|
||||
fac= (*cvalue - (env->midval + env->min)) / (env->max - env->min);
|
||||
*cvalue= min + fac*(max - min);
|
||||
}
|
||||
|
||||
static FModifierTypeInfo FMI_ENVELOPE = {
|
||||
FMODIFIER_TYPE_ENVELOPE, /* type */
|
||||
sizeof(FMod_Envelope), /* size */
|
||||
FMI_TYPE_REPLACE_VALUES, /* action type */
|
||||
0, /* requirements */
|
||||
"Envelope", /* name */
|
||||
"FMod_Envelope", /* struct name */
|
||||
fcm_envelope_free, /* free data */
|
||||
fcm_envelope_copy, /* copy data */
|
||||
fcm_envelope_new_data, /* new data */
|
||||
fcm_envelope_verify, /* verify */
|
||||
NULL, /* evaluate time */
|
||||
fcm_envelope_evaluate /* evaluate */
|
||||
};
|
||||
|
||||
/* Cycles F-Curve Modifier --------------------------- */
|
||||
|
||||
/* This modifier changes evaltime to something that exists within the curve's frame-range,
|
||||
* then re-evaluates modifier stack up to this point using the new time. This re-entrant behaviour
|
||||
* is very likely to be more time-consuming than the original approach... (which was tighly integrated into
|
||||
* the calculation code...).
|
||||
*
|
||||
* NOTE: this needs to be at the start of the stack to be of use, as it needs to know the extents of the keyframes/sample-data
|
||||
* Possible TODO - store length of cycle information that can be initialised from the extents of the keyframes/sample-data, and adjusted
|
||||
* as appropriate
|
||||
*/
|
||||
|
||||
/* temp data used during evaluation */
|
||||
typedef struct tFCMED_Cycles {
|
||||
float cycyofs; /* y-offset to apply */
|
||||
} tFCMED_Cycles;
|
||||
|
||||
static void fcm_cycles_new_data (void *mdata)
|
||||
{
|
||||
FMod_Cycles *data= (FMod_Cycles *)mdata;
|
||||
|
||||
/* turn on cycles by default */
|
||||
data->before_mode= data->after_mode= FCM_EXTRAPOLATE_CYCLIC;
|
||||
}
|
||||
|
||||
static float fcm_cycles_time (FCurve *fcu, FModifier *fcm, float cvalue, float evaltime)
|
||||
{
|
||||
FMod_Cycles *data= (FMod_Cycles *)fcm->data;
|
||||
float prevkey[2], lastkey[2], cycyofs=0.0f;
|
||||
short side=0, mode=0;
|
||||
int cycles=0;
|
||||
|
||||
/* check if modifier is first in stack, otherwise disable ourself... */
|
||||
// FIXME...
|
||||
if (fcm->prev) {
|
||||
fcm->flag |= FMODIFIER_FLAG_DISABLED;
|
||||
return evaltime;
|
||||
}
|
||||
|
||||
/* calculate new evaltime due to cyclic interpolation */
|
||||
if (fcu && fcu->bezt) {
|
||||
BezTriple *prevbezt= fcu->bezt;
|
||||
BezTriple *lastbezt= prevbezt + fcu->totvert-1;
|
||||
|
||||
prevkey[0]= prevbezt->vec[1][0];
|
||||
prevkey[1]= prevbezt->vec[1][1];
|
||||
|
||||
lastkey[0]= lastbezt->vec[1][0];
|
||||
lastkey[1]= lastbezt->vec[1][1];
|
||||
}
|
||||
else if (fcu && fcu->fpt) {
|
||||
FPoint *prevfpt= fcu->fpt;
|
||||
FPoint *lastfpt= prevfpt + fcu->totvert-1;
|
||||
|
||||
prevkey[0]= prevfpt->vec[0];
|
||||
prevkey[1]= prevfpt->vec[1];
|
||||
|
||||
lastkey[0]= lastfpt->vec[0];
|
||||
lastkey[1]= lastfpt->vec[1];
|
||||
}
|
||||
else
|
||||
return evaltime;
|
||||
|
||||
/* check if modifier will do anything
|
||||
* 1) if in data range, definitely don't do anything
|
||||
* 2) if before first frame or after last frame, make sure some cycling is in use
|
||||
*/
|
||||
if (evaltime < prevkey[0]) {
|
||||
if (data->before_mode) {
|
||||
side= -1;
|
||||
mode= data->before_mode;
|
||||
cycles= data->before_cycles;
|
||||
}
|
||||
}
|
||||
else if (evaltime > lastkey[0]) {
|
||||
if (data->after_mode) {
|
||||
side= 1;
|
||||
mode= data->after_mode;
|
||||
cycles= data->after_cycles;
|
||||
}
|
||||
}
|
||||
if ELEM(0, side, mode)
|
||||
return evaltime;
|
||||
|
||||
/* find relative place within a cycle */
|
||||
{
|
||||
float cycdx=0, cycdy=0, ofs=0;
|
||||
float cycle= 0;
|
||||
|
||||
/* ofs is start frame of cycle */
|
||||
ofs= prevkey[0];
|
||||
|
||||
/* calculate period and amplitude (total height) of a cycle */
|
||||
cycdx= lastkey[0] - prevkey[0];
|
||||
cycdy= lastkey[1] - prevkey[1];
|
||||
|
||||
/* check if cycle is infinitely small, to be point of being impossible to use */
|
||||
if (cycdx == 0)
|
||||
return evaltime;
|
||||
|
||||
/* calculate the 'number' of the cycle */
|
||||
cycle= ((float)side * (evaltime - ofs) / cycdx);
|
||||
|
||||
/* check that cyclic is still enabled for the specified time */
|
||||
if (cycles == 0) {
|
||||
/* catch this case so that we don't exit when we have cycles=0
|
||||
* as this indicates infinite cycles...
|
||||
*/
|
||||
}
|
||||
else if (cycle > (cycles+1)) {
|
||||
/* we are too far away from range to evaluate
|
||||
* TODO: but we should still hold last value...
|
||||
*/
|
||||
return evaltime;
|
||||
}
|
||||
|
||||
/* check if 'cyclic extrapolation', and thus calculate y-offset for this cycle */
|
||||
if (mode == FCM_EXTRAPOLATE_CYCLIC_OFFSET) {
|
||||
cycyofs = (float)floor((evaltime - ofs) / cycdx);
|
||||
cycyofs *= cycdy;
|
||||
}
|
||||
|
||||
/* calculate where in the cycle we are (overwrite evaltime to reflect this) */
|
||||
if ((mode == FCM_EXTRAPOLATE_MIRROR) && ((int)(cycle) % 2)) {
|
||||
/* when 'mirror' option is used and cycle number is odd, this cycle is played in reverse
|
||||
* - for 'before' extrapolation, we need to flip in a different way, otherwise values past
|
||||
* then end of the curve get referenced (result of fmod will be negative, and with different phase)
|
||||
*/
|
||||
if (side < 0)
|
||||
evaltime= (float)(prevkey[0] - fmod(evaltime-ofs, cycdx));
|
||||
else
|
||||
evaltime= (float)(lastkey[0] - fmod(evaltime-ofs, cycdx));
|
||||
}
|
||||
else {
|
||||
/* the cycle is played normally... */
|
||||
evaltime= (float)(fmod(evaltime-ofs, cycdx) + ofs);
|
||||
}
|
||||
if (evaltime < ofs) evaltime += cycdx;
|
||||
}
|
||||
|
||||
/* store temp data if needed */
|
||||
if (mode == FCM_EXTRAPOLATE_CYCLIC_OFFSET) {
|
||||
tFCMED_Cycles *edata;
|
||||
|
||||
/* for now, this is just a float, but we could get more stuff... */
|
||||
fcm->edata= edata= MEM_callocN(sizeof(tFCMED_Cycles), "tFCMED_Cycles");
|
||||
edata->cycyofs= cycyofs;
|
||||
}
|
||||
|
||||
/* return the new frame to evaluate */
|
||||
return evaltime;
|
||||
}
|
||||
|
||||
static void fcm_cycles_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
|
||||
{
|
||||
tFCMED_Cycles *edata= (tFCMED_Cycles *)fcm->edata;
|
||||
|
||||
/* use temp data */
|
||||
if (edata) {
|
||||
/* add cyclic offset - no need to check for now, otherwise the data wouldn't exist! */
|
||||
*cvalue += edata->cycyofs;
|
||||
|
||||
/* free temp data */
|
||||
MEM_freeN(edata);
|
||||
fcm->edata= NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static FModifierTypeInfo FMI_CYCLES = {
|
||||
FMODIFIER_TYPE_CYCLES, /* type */
|
||||
sizeof(FMod_Cycles), /* size */
|
||||
FMI_TYPE_EXTRAPOLATION, /* action type */
|
||||
FMI_REQUIRES_ORIGINAL_DATA, /* requirements */
|
||||
"Cycles", /* name */
|
||||
"FMod_Cycles", /* struct name */
|
||||
NULL, /* free data */
|
||||
NULL, /* copy data */
|
||||
fcm_cycles_new_data, /* new data */
|
||||
NULL /*fcm_cycles_verify*/, /* verify */
|
||||
fcm_cycles_time, /* evaluate time */
|
||||
fcm_cycles_evaluate /* evaluate */
|
||||
};
|
||||
|
||||
/* Noise F-Curve Modifier --------------------------- */
|
||||
|
||||
static void fcm_noise_new_data (void *mdata)
|
||||
{
|
||||
FMod_Noise *data= (FMod_Noise *)mdata;
|
||||
|
||||
/* defaults */
|
||||
data->size= 1.0f;
|
||||
data->strength= 1.0f;
|
||||
data->phase= 1.0f;
|
||||
data->depth = 0;
|
||||
data->modification = FCM_NOISE_MODIF_REPLACE;
|
||||
}
|
||||
|
||||
static void fcm_noise_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
|
||||
{
|
||||
FMod_Noise *data= (FMod_Noise *)fcm->data;
|
||||
float noise;
|
||||
|
||||
noise = BLI_turbulence(data->size, evaltime, data->phase, 0.f, data->depth);
|
||||
|
||||
switch (data->modification) {
|
||||
case FCM_NOISE_MODIF_ADD:
|
||||
*cvalue= *cvalue + noise * data->strength;
|
||||
break;
|
||||
case FCM_NOISE_MODIF_SUBTRACT:
|
||||
*cvalue= *cvalue - noise * data->strength;
|
||||
break;
|
||||
case FCM_NOISE_MODIF_MULTIPLY:
|
||||
*cvalue= *cvalue * noise * data->strength;
|
||||
break;
|
||||
case FCM_NOISE_MODIF_REPLACE:
|
||||
default:
|
||||
*cvalue= *cvalue + (noise - 0.5f) * data->strength;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static FModifierTypeInfo FMI_NOISE = {
|
||||
FMODIFIER_TYPE_NOISE, /* type */
|
||||
sizeof(FMod_Noise), /* size */
|
||||
FMI_TYPE_REPLACE_VALUES, /* action type */
|
||||
0, /* requirements */
|
||||
"Noise", /* name */
|
||||
"FMod_Noise", /* struct name */
|
||||
NULL, /* free data */
|
||||
NULL, /* copy data */
|
||||
fcm_noise_new_data, /* new data */
|
||||
NULL /*fcm_noise_verify*/, /* verify */
|
||||
NULL, /* evaluate time */
|
||||
fcm_noise_evaluate /* evaluate */
|
||||
};
|
||||
|
||||
/* Filter F-Curve Modifier --------------------------- */
|
||||
|
||||
#if 0 // XXX not yet implemented
|
||||
static FModifierTypeInfo FMI_FILTER = {
|
||||
FMODIFIER_TYPE_FILTER, /* type */
|
||||
sizeof(FMod_Filter), /* size */
|
||||
FMI_TYPE_REPLACE_VALUES, /* action type */
|
||||
0, /* requirements */
|
||||
"Filter", /* name */
|
||||
"FMod_Filter", /* struct name */
|
||||
NULL, /* free data */
|
||||
NULL, /* copy data */
|
||||
NULL, /* new data */
|
||||
NULL /*fcm_filter_verify*/, /* verify */
|
||||
NULL, /* evlauate time */
|
||||
fcm_filter_evaluate /* evaluate */
|
||||
};
|
||||
#endif // XXX not yet implemented
|
||||
|
||||
|
||||
/* Python F-Curve Modifier --------------------------- */
|
||||
|
||||
static void fcm_python_free (FModifier *fcm)
|
||||
{
|
||||
FMod_Python *data= (FMod_Python *)fcm->data;
|
||||
|
||||
/* id-properties */
|
||||
IDP_FreeProperty(data->prop);
|
||||
MEM_freeN(data->prop);
|
||||
}
|
||||
|
||||
static void fcm_python_new_data (void *mdata)
|
||||
{
|
||||
FMod_Python *data= (FMod_Python *)mdata;
|
||||
|
||||
/* everything should be set correctly by calloc, except for the prop->type constant.*/
|
||||
data->prop = MEM_callocN(sizeof(IDProperty), "PyFModifierProps");
|
||||
data->prop->type = IDP_GROUP;
|
||||
}
|
||||
|
||||
static void fcm_python_copy (FModifier *fcm, FModifier *src)
|
||||
{
|
||||
FMod_Python *pymod = (FMod_Python *)fcm->data;
|
||||
FMod_Python *opymod = (FMod_Python *)src->data;
|
||||
|
||||
pymod->prop = IDP_CopyProperty(opymod->prop);
|
||||
}
|
||||
|
||||
static void fcm_python_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
|
||||
{
|
||||
#ifndef DISABLE_PYTHON
|
||||
//FMod_Python *data= (FMod_Python *)fcm->data;
|
||||
|
||||
/* FIXME... need to implement this modifier...
|
||||
* It will need it execute a script using the custom properties
|
||||
*/
|
||||
#endif /* DISABLE_PYTHON */
|
||||
}
|
||||
|
||||
static FModifierTypeInfo FMI_PYTHON = {
|
||||
FMODIFIER_TYPE_PYTHON, /* type */
|
||||
sizeof(FMod_Python), /* size */
|
||||
FMI_TYPE_GENERATE_CURVE, /* action type */
|
||||
FMI_REQUIRES_RUNTIME_CHECK, /* requirements */
|
||||
"Python", /* name */
|
||||
"FMod_Python", /* struct name */
|
||||
fcm_python_free, /* free data */
|
||||
fcm_python_copy, /* copy data */
|
||||
fcm_python_new_data, /* new data */
|
||||
NULL /*fcm_python_verify*/, /* verify */
|
||||
NULL /*fcm_python_time*/, /* evaluate time */
|
||||
fcm_python_evaluate /* evaluate */
|
||||
};
|
||||
|
||||
|
||||
/* Limits F-Curve Modifier --------------------------- */
|
||||
|
||||
static float fcm_limits_time (FCurve *fcu, FModifier *fcm, float cvalue, float evaltime)
|
||||
{
|
||||
FMod_Limits *data= (FMod_Limits *)fcm->data;
|
||||
|
||||
/* check for the time limits */
|
||||
if ((data->flag & FCM_LIMIT_XMIN) && (evaltime < data->rect.xmin))
|
||||
return data->rect.xmin;
|
||||
if ((data->flag & FCM_LIMIT_XMAX) && (evaltime > data->rect.xmax))
|
||||
return data->rect.xmax;
|
||||
|
||||
/* modifier doesn't change time */
|
||||
return evaltime;
|
||||
}
|
||||
|
||||
static void fcm_limits_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
|
||||
{
|
||||
FMod_Limits *data= (FMod_Limits *)fcm->data;
|
||||
|
||||
/* value limits now */
|
||||
if ((data->flag & FCM_LIMIT_YMIN) && (*cvalue < data->rect.ymin))
|
||||
*cvalue= data->rect.ymin;
|
||||
if ((data->flag & FCM_LIMIT_YMAX) && (*cvalue > data->rect.ymax))
|
||||
*cvalue= data->rect.ymax;
|
||||
}
|
||||
|
||||
static FModifierTypeInfo FMI_LIMITS = {
|
||||
FMODIFIER_TYPE_LIMITS, /* type */
|
||||
sizeof(FMod_Limits), /* size */
|
||||
FMI_TYPE_GENERATE_CURVE, /* action type */ /* XXX... err... */
|
||||
FMI_REQUIRES_RUNTIME_CHECK, /* requirements */
|
||||
"Limits", /* name */
|
||||
"FMod_Limits", /* struct name */
|
||||
NULL, /* free data */
|
||||
NULL, /* copy data */
|
||||
NULL, /* new data */
|
||||
NULL, /* verify */
|
||||
fcm_limits_time, /* evaluate time */
|
||||
fcm_limits_evaluate /* evaluate */
|
||||
};
|
||||
|
||||
/* F-Curve Modifier API --------------------------- */
|
||||
/* All of the F-Curve Modifier api functions use FModifierTypeInfo structs to carry out
|
||||
* and operations that involve F-Curve modifier specific code.
|
||||
*/
|
||||
|
||||
/* These globals only ever get directly accessed in this file */
|
||||
static FModifierTypeInfo *fmodifiersTypeInfo[FMODIFIER_NUM_TYPES];
|
||||
static short FMI_INIT= 1; /* when non-zero, the list needs to be updated */
|
||||
|
||||
/* This function only gets called when FMI_INIT is non-zero */
|
||||
static void fmods_init_typeinfo ()
|
||||
{
|
||||
fmodifiersTypeInfo[0]= NULL; /* 'Null' F-Curve Modifier */
|
||||
fmodifiersTypeInfo[1]= &FMI_GENERATOR; /* Generator F-Curve Modifier */
|
||||
fmodifiersTypeInfo[2]= &FMI_FN_GENERATOR; /* Built-In Function Generator F-Curve Modifier */
|
||||
fmodifiersTypeInfo[3]= &FMI_ENVELOPE; /* Envelope F-Curve Modifier */
|
||||
fmodifiersTypeInfo[4]= &FMI_CYCLES; /* Cycles F-Curve Modifier */
|
||||
fmodifiersTypeInfo[5]= &FMI_NOISE; /* Apply-Noise F-Curve Modifier */
|
||||
fmodifiersTypeInfo[6]= NULL/*&FMI_FILTER*/; /* Filter F-Curve Modifier */ // XXX unimplemented
|
||||
fmodifiersTypeInfo[7]= &FMI_PYTHON; /* Custom Python F-Curve Modifier */
|
||||
fmodifiersTypeInfo[8]= &FMI_LIMITS; /* Limits F-Curve Modifier */
|
||||
}
|
||||
|
||||
/* This function should be used for getting the appropriate type-info when only
|
||||
* a F-Curve modifier type is known
|
||||
*/
|
||||
FModifierTypeInfo *get_fmodifier_typeinfo (int type)
|
||||
{
|
||||
/* initialise the type-info list? */
|
||||
if (FMI_INIT) {
|
||||
fmods_init_typeinfo();
|
||||
FMI_INIT = 0;
|
||||
}
|
||||
|
||||
/* only return for valid types */
|
||||
if ( (type >= FMODIFIER_TYPE_NULL) &&
|
||||
(type <= FMODIFIER_NUM_TYPES ) )
|
||||
{
|
||||
/* there shouldn't be any segfaults here... */
|
||||
return fmodifiersTypeInfo[type];
|
||||
}
|
||||
else {
|
||||
printf("No valid F-Curve Modifier type-info data available. Type = %i \n", type);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* This function should always be used to get the appropriate type-info, as it
|
||||
* has checks which prevent segfaults in some weird cases.
|
||||
*/
|
||||
FModifierTypeInfo *fmodifier_get_typeinfo (FModifier *fcm)
|
||||
{
|
||||
/* only return typeinfo for valid modifiers */
|
||||
if (fcm)
|
||||
return get_fmodifier_typeinfo(fcm->type);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* API --------------------------- */
|
||||
|
||||
/* Add a new F-Curve Modifier to the given F-Curve of a certain type */
|
||||
FModifier *add_fmodifier (ListBase *modifiers, int type)
|
||||
{
|
||||
FModifierTypeInfo *fmi= get_fmodifier_typeinfo(type);
|
||||
FModifier *fcm;
|
||||
|
||||
/* sanity checks */
|
||||
if ELEM(NULL, modifiers, fmi)
|
||||
return NULL;
|
||||
|
||||
/* special checks for whether modifier can be added */
|
||||
if ((modifiers->first) && (type == FMODIFIER_TYPE_CYCLES)) {
|
||||
/* cycles modifier must be first in stack, so for now, don't add if it can't be */
|
||||
// TODO: perhaps there is some better way, but for now,
|
||||
printf("Error: Cannot add 'Cycles' modifier to F-Curve, as 'Cycles' modifier can only be first in stack. \n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* add modifier itself */
|
||||
fcm= MEM_callocN(sizeof(FModifier), "F-Curve Modifier");
|
||||
fcm->type = type;
|
||||
fcm->flag = FMODIFIER_FLAG_EXPANDED;
|
||||
BLI_addtail(modifiers, fcm);
|
||||
|
||||
/* add modifier's data */
|
||||
fcm->data= MEM_callocN(fmi->size, fmi->structName);
|
||||
|
||||
/* init custom settings if necessary */
|
||||
if (fmi->new_data)
|
||||
fmi->new_data(fcm->data);
|
||||
|
||||
/* return modifier for further editing */
|
||||
return fcm;
|
||||
}
|
||||
|
||||
/* Duplicate all of the F-Modifiers in the Modifier stacks */
|
||||
void copy_fmodifiers (ListBase *dst, ListBase *src)
|
||||
{
|
||||
FModifier *fcm, *srcfcm;
|
||||
|
||||
if ELEM(NULL, dst, src)
|
||||
return;
|
||||
|
||||
dst->first= dst->last= NULL;
|
||||
BLI_duplicatelist(dst, src);
|
||||
|
||||
for (fcm=dst->first, srcfcm=src->first; fcm && srcfcm; srcfcm=srcfcm->next, fcm=fcm->next) {
|
||||
FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
|
||||
|
||||
/* make a new copy of the F-Modifier's data */
|
||||
fcm->data = MEM_dupallocN(fcm->data);
|
||||
|
||||
/* only do specific constraints if required */
|
||||
if (fmi && fmi->copy_data)
|
||||
fmi->copy_data(fcm, srcfcm);
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove and free the given F-Modifier from the given stack */
|
||||
void remove_fmodifier (ListBase *modifiers, FModifier *fcm)
|
||||
{
|
||||
FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
|
||||
|
||||
/* sanity check */
|
||||
if (fcm == NULL)
|
||||
return;
|
||||
|
||||
/* free modifier's special data (stored inside fcm->data) */
|
||||
if (fcm->data) {
|
||||
if (fmi && fmi->free_data)
|
||||
fmi->free_data(fcm);
|
||||
|
||||
/* free modifier's data (fcm->data) */
|
||||
MEM_freeN(fcm->data);
|
||||
}
|
||||
|
||||
/* remove modifier from stack */
|
||||
if (modifiers)
|
||||
BLI_freelinkN(modifiers, fcm);
|
||||
else {
|
||||
// XXX this case can probably be removed some day, as it shouldn't happen...
|
||||
printf("remove_fmodifier() - no modifier stack given \n");
|
||||
MEM_freeN(fcm);
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove all of a given F-Curve's modifiers */
|
||||
void free_fmodifiers (ListBase *modifiers)
|
||||
{
|
||||
FModifier *fcm, *fmn;
|
||||
|
||||
/* sanity check */
|
||||
if (modifiers == NULL)
|
||||
return;
|
||||
|
||||
/* free each modifier in order - modifier is unlinked from list and freed */
|
||||
for (fcm= modifiers->first; fcm; fcm= fmn) {
|
||||
fmn= fcm->next;
|
||||
remove_fmodifier(modifiers, fcm);
|
||||
}
|
||||
}
|
||||
|
||||
/* Find the active F-Modifier */
|
||||
FModifier *find_active_fmodifier (ListBase *modifiers)
|
||||
{
|
||||
FModifier *fcm;
|
||||
|
||||
/* sanity checks */
|
||||
if ELEM(NULL, modifiers, modifiers->first)
|
||||
return NULL;
|
||||
|
||||
/* loop over modifiers until 'active' one is found */
|
||||
for (fcm= modifiers->first; fcm; fcm= fcm->next) {
|
||||
if (fcm->flag & FMODIFIER_FLAG_ACTIVE)
|
||||
return fcm;
|
||||
}
|
||||
|
||||
/* no modifier is active */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Set the active F-Modifier */
|
||||
void set_active_fmodifier (ListBase *modifiers, FModifier *fcm)
|
||||
{
|
||||
FModifier *fm;
|
||||
|
||||
/* sanity checks */
|
||||
if ELEM(NULL, modifiers, modifiers->first)
|
||||
return;
|
||||
|
||||
/* deactivate all, and set current one active */
|
||||
for (fm= modifiers->first; fm; fm= fm->next)
|
||||
fm->flag &= ~FMODIFIER_FLAG_ACTIVE;
|
||||
|
||||
/* make given modifier active */
|
||||
if (fcm)
|
||||
fcm->flag |= FMODIFIER_FLAG_ACTIVE;
|
||||
}
|
||||
|
||||
/* Do we have any modifiers which match certain criteria
|
||||
* - mtype - type of modifier (if 0, doesn't matter)
|
||||
* - acttype - type of action to perform (if -1, doesn't matter)
|
||||
*/
|
||||
short list_has_suitable_fmodifier (ListBase *modifiers, int mtype, short acttype)
|
||||
{
|
||||
FModifier *fcm;
|
||||
|
||||
/* if there are no specific filtering criteria, just skip */
|
||||
if ((mtype == 0) && (acttype == 0))
|
||||
return (modifiers && modifiers->first);
|
||||
|
||||
/* sanity checks */
|
||||
if ELEM(NULL, modifiers, modifiers->first)
|
||||
return 0;
|
||||
|
||||
/* find the first mdifier fitting these criteria */
|
||||
for (fcm= modifiers->first; fcm; fcm= fcm->next) {
|
||||
FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
|
||||
short mOk=1, aOk=1; /* by default 1, so that when only one test, won't fail */
|
||||
|
||||
/* check if applicable ones are fullfilled */
|
||||
if (mtype)
|
||||
mOk= (fcm->type == mtype);
|
||||
if (acttype > -1)
|
||||
aOk= (fmi->acttype == acttype);
|
||||
|
||||
/* if both are ok, we've found a hit */
|
||||
if (mOk && aOk)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* no matches */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Evaluation API --------------------------- */
|
||||
|
||||
/* evaluate time modifications imposed by some F-Curve Modifiers
|
||||
* - this step acts as an optimisation to prevent the F-Curve stack being evaluated
|
||||
* several times by modifiers requesting the time be modified, as the final result
|
||||
* would have required using the modified time
|
||||
* - modifiers only ever recieve the unmodified time, as subsequent modifiers should be
|
||||
* working on the 'global' result of the modified curve, not some localised segment,
|
||||
* so nevaltime gets set to whatever the last time-modifying modifier likes...
|
||||
* - we start from the end of the stack, as only the last one matters for now
|
||||
*/
|
||||
float evaluate_time_fmodifiers (ListBase *modifiers, FCurve *fcu, float cvalue, float evaltime)
|
||||
{
|
||||
FModifier *fcm;
|
||||
float m_evaltime= evaltime;
|
||||
|
||||
/* sanity checks */
|
||||
if ELEM(NULL, modifiers, modifiers->last)
|
||||
return evaltime;
|
||||
|
||||
/* find the first modifier from end of stack that modifies time, and calculate the time the modifier
|
||||
* would calculate time at
|
||||
*/
|
||||
for (fcm= modifiers->last; fcm; fcm= fcm->prev) {
|
||||
FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
|
||||
|
||||
/* only evaluate if there's a callback for this */
|
||||
// TODO: implement the 'influence' control feature...
|
||||
if (fmi && fmi->evaluate_modifier_time) {
|
||||
if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0)
|
||||
m_evaltime= fmi->evaluate_modifier_time(fcu, fcm, cvalue, evaltime);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* return the modified evaltime */
|
||||
return m_evaltime;
|
||||
}
|
||||
|
||||
/* Evalautes the given set of F-Curve Modifiers using the given data
|
||||
* Should only be called after evaluate_time_fmodifiers() has been called...
|
||||
*/
|
||||
void evaluate_value_fmodifiers (ListBase *modifiers, FCurve *fcu, float *cvalue, float evaltime)
|
||||
{
|
||||
FModifier *fcm;
|
||||
|
||||
/* sanity checks */
|
||||
if ELEM(NULL, modifiers, modifiers->first)
|
||||
return;
|
||||
|
||||
/* evaluate modifiers */
|
||||
for (fcm= modifiers->first; fcm; fcm= fcm->next) {
|
||||
FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
|
||||
|
||||
/* only evaluate if there's a callback for this */
|
||||
// TODO: implement the 'influence' control feature...
|
||||
if (fmi && fmi->evaluate_modifier) {
|
||||
if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0)
|
||||
fmi->evaluate_modifier(fcu, fcm, cvalue, evaltime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------- */
|
||||
|
||||
/* Bake modifiers for given F-Curve to curve sample data, in the frame range defined
|
||||
* by start and end (inclusive).
|
||||
*/
|
||||
void fcurve_bake_modifiers (FCurve *fcu, int start, int end)
|
||||
{
|
||||
ChannelDriver *driver;
|
||||
|
||||
/* sanity checks */
|
||||
// TODO: make these tests report errors using reports not printf's
|
||||
if ELEM(NULL, fcu, fcu->modifiers.first) {
|
||||
printf("Error: No F-Curve with F-Curve Modifiers to Bake\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* temporarily, disable driver while we sample, so that they don't influence the outcome */
|
||||
driver= fcu->driver;
|
||||
fcu->driver= NULL;
|
||||
|
||||
/* bake the modifiers, by sampling the curve at each frame */
|
||||
fcurve_store_samples(fcu, NULL, start, end, fcurve_samplingcb_evalcurve);
|
||||
|
||||
/* free the modifiers now */
|
||||
free_fmodifiers(&fcu->modifiers);
|
||||
|
||||
/* restore driver */
|
||||
fcu->driver= driver;
|
||||
}
|
||||
@@ -58,6 +58,7 @@
|
||||
#include "DNA_key_types.h"
|
||||
#include "DNA_material_types.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_nla_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_object_force.h"
|
||||
#include "DNA_particle_types.h"
|
||||
@@ -85,6 +86,7 @@
|
||||
#include "BKE_library.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_nla.h"
|
||||
#include "BKE_object.h"
|
||||
|
||||
|
||||
@@ -825,6 +827,10 @@ char *get_rna_access (int blocktype, int adrcode, char actname[], char constname
|
||||
char buf[512];
|
||||
int dummy_index= 0;
|
||||
|
||||
/* hack: if constname is set, we can only be dealing with an Constraint curve */
|
||||
if (constname)
|
||||
blocktype= ID_CO;
|
||||
|
||||
/* get property name based on blocktype */
|
||||
switch (blocktype) {
|
||||
case ID_OB: /* object */
|
||||
@@ -840,7 +846,7 @@ char *get_rna_access (int blocktype, int adrcode, char actname[], char constname
|
||||
break;
|
||||
|
||||
case ID_CO: /* constraint */
|
||||
propname= constraint_adrcodes_to_paths(adrcode, &dummy_index);
|
||||
propname= constraint_adrcodes_to_paths(adrcode, &dummy_index);
|
||||
break;
|
||||
|
||||
case ID_TE: /* texture */
|
||||
@@ -870,7 +876,10 @@ char *get_rna_access (int blocktype, int adrcode, char actname[], char constname
|
||||
|
||||
/* XXX problematic blocktypes */
|
||||
case ID_CU: /* curve */
|
||||
propname= "speed"; // XXX this was a 'dummy curve' that didn't really correspond to any real var...
|
||||
/* this used to be a 'dummy' curve which got evaluated on the fly...
|
||||
* now we've got real var for this!
|
||||
*/
|
||||
propname= "eval_time";
|
||||
break;
|
||||
|
||||
case ID_SEQ: /* sequencer strip */
|
||||
@@ -1144,7 +1153,7 @@ static void icu_to_fcurves (ListBase *groups, ListBase *list, IpoCurve *icu, cha
|
||||
/* Add a new FModifier (Cyclic) instead of setting extend value
|
||||
* as that's the new equivilant of that option.
|
||||
*/
|
||||
FModifier *fcm= fcurve_add_modifier(fcu, FMODIFIER_TYPE_CYCLES);
|
||||
FModifier *fcm= add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_CYCLES);
|
||||
FMod_Cycles *data= (FMod_Cycles *)fcm->data;
|
||||
|
||||
/* if 'offset' one is in use, set appropriate settings */
|
||||
@@ -1463,6 +1472,87 @@ static void action_to_animdata (ID *id, bAction *act)
|
||||
action_to_animato(act, &adt->action->groups, &adt->action->curves, &adt->drivers);
|
||||
}
|
||||
|
||||
/* ------------------------- */
|
||||
|
||||
// TODO:
|
||||
// - NLA group duplicators info
|
||||
// - NLA curve/stride modifiers...
|
||||
|
||||
/* Convert NLA-Strip to new system */
|
||||
static void nlastrips_to_animdata (ID *id, ListBase *strips)
|
||||
{
|
||||
AnimData *adt= BKE_animdata_from_id(id);
|
||||
NlaTrack *nlt = NULL;
|
||||
NlaStrip *strip;
|
||||
bActionStrip *as, *asn;
|
||||
|
||||
/* for each one of the original strips, convert to a new strip and free the old... */
|
||||
for (as= strips->first; as; as= asn) {
|
||||
asn= as->next;
|
||||
|
||||
/* this old strip is only worth something if it had an action... */
|
||||
if (as->act) {
|
||||
/* convert Action data (if not yet converted), storing the results in the same Action */
|
||||
action_to_animato(as->act, &as->act->groups, &as->act->curves, &adt->drivers);
|
||||
|
||||
/* create a new-style NLA-strip which references this Action, then copy over relevant settings */
|
||||
{
|
||||
/* init a new strip, and assign the action to it
|
||||
* - no need to muck around with the user-counts, since this is just
|
||||
* passing over the ref to the new owner, not creating an additional ref
|
||||
*/
|
||||
strip= MEM_callocN(sizeof(NlaStrip), "NlaStrip");
|
||||
strip->act= as->act;
|
||||
|
||||
/* endpoints */
|
||||
strip->start= as->start;
|
||||
strip->end= as->end;
|
||||
strip->actstart= as->actstart;
|
||||
strip->actend= as->actend;
|
||||
|
||||
/* action reuse */
|
||||
strip->repeat= as->repeat;
|
||||
strip->scale= as->scale;
|
||||
if (as->flag & ACTSTRIP_LOCK_ACTION) strip->flag |= NLASTRIP_FLAG_SYNC_LENGTH;
|
||||
|
||||
/* blending */
|
||||
strip->blendin= as->blendin;
|
||||
strip->blendout= as->blendout;
|
||||
strip->blendmode= (as->mode==ACTSTRIPMODE_ADD) ? NLASTRIP_MODE_ADD : NLASTRIP_MODE_REPLACE;
|
||||
if (as->flag & ACTSTRIP_AUTO_BLENDS) strip->flag |= NLASTRIP_FLAG_AUTO_BLENDS;
|
||||
|
||||
/* assorted setting flags */
|
||||
if (as->flag & ACTSTRIP_SELECT) strip->flag |= NLASTRIP_FLAG_SELECT;
|
||||
if (as->flag & ACTSTRIP_ACTIVE) strip->flag |= NLASTRIP_FLAG_ACTIVE;
|
||||
|
||||
if (as->flag & ACTSTRIP_MUTE) strip->flag |= NLASTRIP_FLAG_MUTED;
|
||||
if (as->flag & ACTSTRIP_REVERSE) strip->flag |= NLASTRIP_FLAG_REVERSE;
|
||||
|
||||
/* by default, we now always extrapolate, while in the past this was optional */
|
||||
if ((as->flag & ACTSTRIP_HOLDLASTFRAME)==0)
|
||||
strip->extendmode= NLASTRIP_EXTEND_NOTHING;
|
||||
}
|
||||
|
||||
/* try to add this strip to the current NLA-Track (i.e. the 'last' one on the stack atm) */
|
||||
if (BKE_nlatrack_add_strip(nlt, strip) == 0) {
|
||||
/* trying to add to the current failed (no space),
|
||||
* so add a new track to the stack, and add to that...
|
||||
*/
|
||||
nlt= add_nlatrack(adt, NULL);
|
||||
BKE_nlatrack_add_strip(nlt, strip);
|
||||
}
|
||||
}
|
||||
|
||||
/* modifiers */
|
||||
// FIXME: for now, we just free them...
|
||||
if (as->modifiers.first)
|
||||
BLI_freelistN(&as->modifiers);
|
||||
|
||||
/* free the old strip */
|
||||
BLI_freelinkN(strips, as);
|
||||
}
|
||||
}
|
||||
|
||||
/* *************************************************** */
|
||||
/* External API - Only Called from do_versions() */
|
||||
|
||||
@@ -1509,7 +1599,30 @@ void do_versions_ipos_to_animato(Main *main)
|
||||
if (G.f & G_DEBUG) printf("\tconverting ob %s \n", id->name+2);
|
||||
|
||||
/* check if object has any animation data */
|
||||
if ((ob->ipo) || (ob->action) || (ob->nlastrips.first)) {
|
||||
if (ob->nlastrips.first) {
|
||||
/* Add AnimData block */
|
||||
adt= BKE_id_add_animdata(id);
|
||||
|
||||
/* IPO first to take into any non-NLA'd Object Animation */
|
||||
if (ob->ipo) {
|
||||
ipo_to_animdata(id, ob->ipo, NULL, NULL);
|
||||
|
||||
ob->ipo->id.us--;
|
||||
ob->ipo= NULL;
|
||||
}
|
||||
|
||||
/* Action is skipped since it'll be used by some strip in the NLA anyway,
|
||||
* causing errors with evaluation in the new evaluation pipeline
|
||||
*/
|
||||
if (ob->action) {
|
||||
ob->action->id.us--;
|
||||
ob->action= NULL;
|
||||
}
|
||||
|
||||
/* finally NLA */
|
||||
nlastrips_to_animdata(id, &ob->nlastrips);
|
||||
}
|
||||
else if ((ob->ipo) || (ob->action)) {
|
||||
/* Add AnimData block */
|
||||
adt= BKE_id_add_animdata(id);
|
||||
|
||||
@@ -1530,9 +1643,6 @@ void do_versions_ipos_to_animato(Main *main)
|
||||
ob->ipo->id.us--;
|
||||
ob->ipo= NULL;
|
||||
}
|
||||
|
||||
/* finally NLA */
|
||||
// XXX todo... for now, new NLA code not hooked up yet, so keep old stuff (but not for too long!)
|
||||
}
|
||||
|
||||
/* check PoseChannels for constraints with local data */
|
||||
|
||||
@@ -17,171 +17,1433 @@
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
* The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
* Contributor(s): Joshua Leung (full recode)
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_ghash.h"
|
||||
|
||||
#include "DNA_space_types.h"
|
||||
#include "DNA_nla_types.h"
|
||||
#include "DNA_anim_types.h"
|
||||
#include "DNA_action_types.h"
|
||||
#include "DNA_ID.h"
|
||||
#include "DNA_ipo_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
|
||||
#include "BKE_nla.h"
|
||||
#include "BKE_animsys.h"
|
||||
#include "BKE_action.h"
|
||||
#include "BKE_fcurve.h"
|
||||
#include "BKE_nla.h"
|
||||
#include "BKE_blender.h"
|
||||
#include "BKE_library.h"
|
||||
#include "BKE_object.h" /* for convert_action_to_strip(ob) */
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_utildefines.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "nla_private.h"
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
/* NOTE: in group.c the strips get copied for group-nla override, this assumes
|
||||
that strips are one single block, without additional data to be copied */
|
||||
|
||||
void copy_actionstrip (bActionStrip **dst, bActionStrip **src){
|
||||
bActionStrip *dstrip;
|
||||
bActionStrip *sstrip = *src;
|
||||
/* *************************************************** */
|
||||
/* Data Management */
|
||||
|
||||
if (!*src){
|
||||
*dst=NULL;
|
||||
/* Freeing ------------------------------------------- */
|
||||
|
||||
/* Remove the given NLA strip from the NLA track it occupies, free the strip's data,
|
||||
* and the strip itself.
|
||||
*/
|
||||
void free_nlastrip (ListBase *strips, NlaStrip *strip)
|
||||
{
|
||||
NlaStrip *cs, *csn;
|
||||
|
||||
/* sanity checks */
|
||||
if (strip == NULL)
|
||||
return;
|
||||
|
||||
/* free child-strips */
|
||||
for (cs= strip->strips.first; cs; cs= csn) {
|
||||
csn= cs->next;
|
||||
free_nlastrip(&strip->strips, cs);
|
||||
}
|
||||
|
||||
*dst = MEM_dupallocN(sstrip);
|
||||
|
||||
dstrip = *dst;
|
||||
if (dstrip->act)
|
||||
dstrip->act->id.us++;
|
||||
|
||||
if (dstrip->ipo)
|
||||
dstrip->ipo->id.us++;
|
||||
|
||||
/* remove reference to action */
|
||||
if (strip->act)
|
||||
strip->act->id.us--;
|
||||
|
||||
/* free remapping info */
|
||||
//if (strip->remap)
|
||||
// BKE_animremap_free();
|
||||
|
||||
if (dstrip->modifiers.first) {
|
||||
BLI_duplicatelist (&dstrip->modifiers, &sstrip->modifiers);
|
||||
}
|
||||
/* free own F-Curves */
|
||||
free_fcurves(&strip->fcurves);
|
||||
|
||||
/* free own F-Modifiers */
|
||||
free_fmodifiers(&strip->modifiers);
|
||||
|
||||
/* free the strip itself */
|
||||
if (strips)
|
||||
BLI_freelinkN(strips, strip);
|
||||
else
|
||||
MEM_freeN(strip);
|
||||
}
|
||||
|
||||
void copy_nlastrips (ListBase *dst, ListBase *src)
|
||||
/* Remove the given NLA track from the set of NLA tracks, free the track's data,
|
||||
* and the track itself.
|
||||
*/
|
||||
void free_nlatrack (ListBase *tracks, NlaTrack *nlt)
|
||||
{
|
||||
bActionStrip *strip;
|
||||
|
||||
dst->first=dst->last=NULL;
|
||||
|
||||
BLI_duplicatelist (dst, src);
|
||||
|
||||
/* Update specific data */
|
||||
if (!dst->first)
|
||||
NlaStrip *strip, *stripn;
|
||||
|
||||
/* sanity checks */
|
||||
if (nlt == NULL)
|
||||
return;
|
||||
|
||||
/* free strips */
|
||||
for (strip= nlt->strips.first; strip; strip= stripn) {
|
||||
stripn= strip->next;
|
||||
free_nlastrip(&nlt->strips, strip);
|
||||
}
|
||||
|
||||
/* free NLA track itself now */
|
||||
if (tracks)
|
||||
BLI_freelinkN(tracks, nlt);
|
||||
else
|
||||
MEM_freeN(nlt);
|
||||
}
|
||||
|
||||
for (strip = dst->first; strip; strip=strip->next){
|
||||
if (strip->act)
|
||||
strip->act->id.us++;
|
||||
if (strip->ipo)
|
||||
strip->ipo->id.us++;
|
||||
if (strip->modifiers.first) {
|
||||
ListBase listb;
|
||||
BLI_duplicatelist (&listb, &strip->modifiers);
|
||||
strip->modifiers= listb;
|
||||
/* Free the elements of type NLA Tracks provided in the given list, but do not free
|
||||
* the list itself since that is not free-standing
|
||||
*/
|
||||
void free_nladata (ListBase *tracks)
|
||||
{
|
||||
NlaTrack *nlt, *nltn;
|
||||
|
||||
/* sanity checks */
|
||||
if ELEM(NULL, tracks, tracks->first)
|
||||
return;
|
||||
|
||||
/* free tracks one by one */
|
||||
for (nlt= tracks->first; nlt; nlt= nltn) {
|
||||
nltn= nlt->next;
|
||||
free_nlatrack(tracks, nlt);
|
||||
}
|
||||
|
||||
/* clear the list's pointers to be safe */
|
||||
tracks->first= tracks->last= NULL;
|
||||
}
|
||||
|
||||
/* Copying ------------------------------------------- */
|
||||
|
||||
/* Copy NLA strip */
|
||||
NlaStrip *copy_nlastrip (NlaStrip *strip)
|
||||
{
|
||||
NlaStrip *strip_d;
|
||||
NlaStrip *cs, *cs_d;
|
||||
|
||||
/* sanity check */
|
||||
if (strip == NULL)
|
||||
return NULL;
|
||||
|
||||
/* make a copy */
|
||||
strip_d= MEM_dupallocN(strip);
|
||||
strip_d->next= strip_d->prev= NULL;
|
||||
|
||||
/* increase user-count of action */
|
||||
if (strip_d->act)
|
||||
strip_d->act->id.us++;
|
||||
|
||||
/* copy F-Curves and modifiers */
|
||||
copy_fcurves(&strip_d->fcurves, &strip->fcurves);
|
||||
copy_fmodifiers(&strip_d->modifiers, &strip->modifiers);
|
||||
|
||||
/* make a copy of all the child-strips, one at a time */
|
||||
strip_d->strips.first= strip_d->strips.last= NULL;
|
||||
|
||||
for (cs= strip->strips.first; cs; cs= cs->next) {
|
||||
cs_d= copy_nlastrip(cs);
|
||||
BLI_addtail(&strip_d->strips, cs_d);
|
||||
}
|
||||
|
||||
/* return the strip */
|
||||
return strip_d;
|
||||
}
|
||||
|
||||
/* Copy NLA Track */
|
||||
NlaTrack *copy_nlatrack (NlaTrack *nlt)
|
||||
{
|
||||
NlaStrip *strip, *strip_d;
|
||||
NlaTrack *nlt_d;
|
||||
|
||||
/* sanity check */
|
||||
if (nlt == NULL)
|
||||
return NULL;
|
||||
|
||||
/* make a copy */
|
||||
nlt_d= MEM_dupallocN(nlt);
|
||||
nlt_d->next= nlt_d->prev= NULL;
|
||||
|
||||
/* make a copy of all the strips, one at a time */
|
||||
nlt_d->strips.first= nlt_d->strips.last= NULL;
|
||||
|
||||
for (strip= nlt->strips.first; strip; strip= strip->next) {
|
||||
strip_d= copy_nlastrip(strip);
|
||||
BLI_addtail(&nlt_d->strips, strip_d);
|
||||
}
|
||||
|
||||
/* return the copy */
|
||||
return nlt_d;
|
||||
}
|
||||
|
||||
/* Copy all NLA data */
|
||||
void copy_nladata (ListBase *dst, ListBase *src)
|
||||
{
|
||||
NlaTrack *nlt, *nlt_d;
|
||||
|
||||
/* sanity checks */
|
||||
if ELEM(NULL, dst, src)
|
||||
return;
|
||||
|
||||
/* copy each NLA-track, one at a time */
|
||||
for (nlt= src->first; nlt; nlt= nlt->next) {
|
||||
/* make a copy, and add the copy to the destination list */
|
||||
nlt_d= copy_nlatrack(nlt);
|
||||
BLI_addtail(dst, nlt_d);
|
||||
}
|
||||
}
|
||||
|
||||
/* Adding ------------------------------------------- */
|
||||
|
||||
/* Add a NLA Track to the given AnimData
|
||||
* - prev: NLA-Track to add the new one after
|
||||
*/
|
||||
NlaTrack *add_nlatrack (AnimData *adt, NlaTrack *prev)
|
||||
{
|
||||
NlaTrack *nlt;
|
||||
|
||||
/* sanity checks */
|
||||
if (adt == NULL)
|
||||
return NULL;
|
||||
|
||||
/* allocate new track */
|
||||
nlt= MEM_callocN(sizeof(NlaTrack), "NlaTrack");
|
||||
|
||||
/* set settings requiring the track to not be part of the stack yet */
|
||||
nlt->flag = NLATRACK_SELECTED;
|
||||
nlt->index= BLI_countlist(&adt->nla_tracks);
|
||||
|
||||
/* add track to stack, and make it the active one */
|
||||
if (prev)
|
||||
BLI_insertlinkafter(&adt->nla_tracks, prev, nlt);
|
||||
else
|
||||
BLI_addtail(&adt->nla_tracks, nlt);
|
||||
BKE_nlatrack_set_active(&adt->nla_tracks, nlt);
|
||||
|
||||
/* must have unique name, but we need to seed this */
|
||||
sprintf(nlt->name, "NlaTrack");
|
||||
BLI_uniquename(&adt->nla_tracks, nlt, "NlaTrack", '.', offsetof(NlaTrack, name), 64);
|
||||
|
||||
/* return the new track */
|
||||
return nlt;
|
||||
}
|
||||
|
||||
/* Add a NLA Strip referencing the given Action */
|
||||
NlaStrip *add_nlastrip (bAction *act)
|
||||
{
|
||||
NlaStrip *strip;
|
||||
|
||||
/* sanity checks */
|
||||
if (act == NULL)
|
||||
return NULL;
|
||||
|
||||
/* allocate new strip */
|
||||
strip= MEM_callocN(sizeof(NlaStrip), "NlaStrip");
|
||||
|
||||
/* generic settings
|
||||
* - selected flag to highlight this to the user
|
||||
* - auto-blends to ensure that blend in/out values are automatically
|
||||
* determined by overlaps of strips
|
||||
* - (XXX) synchronisation of strip-length in accordance with changes to action-length
|
||||
* is not done though, since this should only really happens in editmode for strips now
|
||||
* though this decision is still subject to further review...
|
||||
*/
|
||||
strip->flag = NLASTRIP_FLAG_SELECT|NLASTRIP_FLAG_AUTO_BLENDS;
|
||||
|
||||
/* assign the action reference */
|
||||
strip->act= act;
|
||||
id_us_plus(&act->id);
|
||||
|
||||
/* determine initial range
|
||||
* - strip length cannot be 0... ever...
|
||||
*/
|
||||
calc_action_range(strip->act, &strip->actstart, &strip->actend, 1);
|
||||
|
||||
strip->start = strip->actstart;
|
||||
strip->end = (IS_EQ(strip->actstart, strip->actend)) ? (strip->actstart + 1.0f): (strip->actend);
|
||||
|
||||
/* strip should be referenced as-is */
|
||||
strip->scale= 1.0f;
|
||||
strip->repeat = 1.0f;
|
||||
|
||||
/* return the new strip */
|
||||
return strip;
|
||||
}
|
||||
|
||||
/* Add new NLA-strip to the top of the NLA stack - i.e. into the last track if space, or a new one otherwise */
|
||||
NlaStrip *add_nlastrip_to_stack (AnimData *adt, bAction *act)
|
||||
{
|
||||
NlaStrip *strip;
|
||||
NlaTrack *nlt;
|
||||
|
||||
/* sanity checks */
|
||||
if ELEM(NULL, adt, act)
|
||||
return NULL;
|
||||
|
||||
/* create a new NLA strip */
|
||||
strip= add_nlastrip(act);
|
||||
if (strip == NULL)
|
||||
return NULL;
|
||||
|
||||
/* firstly try adding strip to last track, but if that fails, add to a new track */
|
||||
if (BKE_nlatrack_add_strip(adt->nla_tracks.last, strip) == 0) {
|
||||
/* trying to add to the last track failed (no track or no space),
|
||||
* so add a new track to the stack, and add to that...
|
||||
*/
|
||||
nlt= add_nlatrack(adt, NULL);
|
||||
BKE_nlatrack_add_strip(nlt, strip);
|
||||
}
|
||||
|
||||
/* automatically name it too */
|
||||
BKE_nlastrip_validate_name(adt, strip);
|
||||
|
||||
/* returns the strip added */
|
||||
return strip;
|
||||
}
|
||||
|
||||
/* *************************************************** */
|
||||
/* NLA Evaluation <-> Editing Stuff */
|
||||
|
||||
/* Strip Mapping ------------------------------------- */
|
||||
|
||||
/* non clipped mapping for strip-time <-> global time (for Action-Clips)
|
||||
* invert = convert action-strip time to global time
|
||||
*/
|
||||
static float nlastrip_get_frame_actionclip (NlaStrip *strip, float cframe, short mode)
|
||||
{
|
||||
float actlength, repeat, scale;
|
||||
|
||||
/* get number of repeats */
|
||||
if (IS_EQ(strip->repeat, 0.0f)) strip->repeat = 1.0f;
|
||||
repeat = strip->repeat;
|
||||
|
||||
/* scaling */
|
||||
if (IS_EQ(strip->scale, 0.0f)) strip->scale= 1.0f;
|
||||
scale = (float)fabs(strip->scale); /* scale must be positive - we've got a special flag for reversing */
|
||||
|
||||
/* length of referenced action */
|
||||
actlength = strip->actend - strip->actstart;
|
||||
if (IS_EQ(actlength, 0.0f)) actlength = 1.0f;
|
||||
|
||||
/* reversed = play strip backwards */
|
||||
if (strip->flag & NLASTRIP_FLAG_REVERSE) {
|
||||
// FIXME: this won't work right with Graph Editor?
|
||||
if (mode == NLATIME_CONVERT_MAP) {
|
||||
return strip->end - scale*(cframe - strip->actstart);
|
||||
}
|
||||
else if (mode == NLATIME_CONVERT_UNMAP) {
|
||||
int repeatsNum = (int)((cframe - strip->start) / (actlength * scale));
|
||||
|
||||
/* this method doesn't clip the values to lie within the action range only
|
||||
* - the '(repeatsNum * actlength * scale)' compensates for the fmod(...)
|
||||
* - the fmod(...) works in the same way as for eval
|
||||
*/
|
||||
return strip->actend - (repeatsNum * actlength * scale)
|
||||
- (fmod(cframe - strip->start, actlength*scale) / scale);
|
||||
}
|
||||
else {
|
||||
if (IS_EQ(cframe, strip->end) && IS_EQ(strip->repeat, ((int)strip->repeat))) {
|
||||
/* this case prevents the motion snapping back to the first frame at the end of the strip
|
||||
* by catching the case where repeats is a whole number, which means that the end of the strip
|
||||
* could also be interpreted as the end of the start of a repeat
|
||||
*/
|
||||
return strip->actstart;
|
||||
}
|
||||
else {
|
||||
/* - the 'fmod(..., actlength*scale)' is needed to get the repeats working
|
||||
* - the '/ scale' is needed to ensure that scaling influences the timing within the repeat
|
||||
*/
|
||||
return strip->actend - fmod(cframe - strip->start, actlength*scale) / scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (mode == NLATIME_CONVERT_MAP) {
|
||||
return strip->start + scale*(cframe - strip->actstart);
|
||||
}
|
||||
else if (mode == NLATIME_CONVERT_UNMAP) {
|
||||
int repeatsNum = (int)((cframe - strip->start) / (actlength * scale));
|
||||
|
||||
/* this method doesn't clip the values to lie within the action range only
|
||||
* - the '(repeatsNum * actlength * scale)' compensates for the fmod(...)
|
||||
* - the fmod(...) works in the same way as for eval
|
||||
*/
|
||||
return strip->actstart + (repeatsNum * actlength * scale)
|
||||
+ (fmod(cframe - strip->start, actlength*scale) / scale);
|
||||
}
|
||||
else /* if (mode == NLATIME_CONVERT_EVAL) */{
|
||||
if (IS_EQ(cframe, strip->end) && IS_EQ(strip->repeat, ((int)strip->repeat))) {
|
||||
/* this case prevents the motion snapping back to the first frame at the end of the strip
|
||||
* by catching the case where repeats is a whole number, which means that the end of the strip
|
||||
* could also be interpreted as the end of the start of a repeat
|
||||
*/
|
||||
return strip->actend;
|
||||
}
|
||||
else {
|
||||
/* - the 'fmod(..., actlength*scale)' is needed to get the repeats working
|
||||
* - the '/ scale' is needed to ensure that scaling influences the timing within the repeat
|
||||
*/
|
||||
return strip->actstart + fmod(cframe - strip->start, actlength*scale) / scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* from editnla, for convert_action_to_strip -- no UI code so should be ok here.. */
|
||||
void find_stridechannel(Object *ob, bActionStrip *strip)
|
||||
/* non clipped mapping for strip-time <-> global time (for Transitions)
|
||||
* invert = convert action-strip time to global time
|
||||
*/
|
||||
static float nlastrip_get_frame_transition (NlaStrip *strip, float cframe, short mode)
|
||||
{
|
||||
if(ob && ob->pose) {
|
||||
bPoseChannel *pchan;
|
||||
for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next)
|
||||
if(pchan->flag & POSE_STRIDE)
|
||||
break;
|
||||
if(pchan)
|
||||
BLI_strncpy(strip->stridechannel, pchan->name, 32);
|
||||
float length;
|
||||
|
||||
/* length of strip */
|
||||
length= strip->end - strip->start;
|
||||
|
||||
/* reversed = play strip backwards */
|
||||
if (strip->flag & NLASTRIP_FLAG_REVERSE) {
|
||||
if (mode == NLATIME_CONVERT_MAP)
|
||||
return strip->end - (length * cframe);
|
||||
else
|
||||
strip->stridechannel[0]= 0;
|
||||
return (strip->end - cframe) / length;
|
||||
}
|
||||
else {
|
||||
if (mode == NLATIME_CONVERT_MAP)
|
||||
return (length * cframe) + strip->start;
|
||||
else
|
||||
return (cframe - strip->start) / length;
|
||||
}
|
||||
}
|
||||
|
||||
//called by convert_nla / bpy api with an object with the action to be converted to a new strip
|
||||
bActionStrip *convert_action_to_strip (Object *ob)
|
||||
/* non clipped mapping for strip-time <-> global time
|
||||
* mode = eNlaTime_ConvertModes[] -> NLATIME_CONVERT_*
|
||||
*
|
||||
* only secure for 'internal' (i.e. within AnimSys evaluation) operations,
|
||||
* but should not be directly relied on for stuff which interacts with editors
|
||||
*/
|
||||
float nlastrip_get_frame (NlaStrip *strip, float cframe, short mode)
|
||||
{
|
||||
bActionStrip *nstrip;
|
||||
|
||||
/* Make new actionstrip */
|
||||
nstrip = MEM_callocN(sizeof(bActionStrip), "bActionStrip");
|
||||
|
||||
/* Link the action to the nstrip */
|
||||
nstrip->act = ob->action;
|
||||
id_us_plus(&nstrip->act->id);
|
||||
calc_action_range(nstrip->act, &nstrip->actstart, &nstrip->actend, 1);
|
||||
nstrip->start = nstrip->actstart;
|
||||
nstrip->end = nstrip->actend;
|
||||
nstrip->flag = ACTSTRIP_SELECT|ACTSTRIP_LOCK_ACTION;
|
||||
|
||||
find_stridechannel(ob, nstrip);
|
||||
//set_active_strip(ob, nstrip); /* is in editnla as does UI calls */
|
||||
|
||||
nstrip->repeat = 1.0;
|
||||
|
||||
if(ob->nlastrips.first == NULL)
|
||||
ob->nlaflag |= OB_NLA_OVERRIDE;
|
||||
|
||||
BLI_addtail(&ob->nlastrips, nstrip);
|
||||
return nstrip; /* is created, malloced etc. here so is safe to just return the pointer?
|
||||
this is needed for setting this active in UI, and probably useful for API too */
|
||||
|
||||
switch (strip->type) {
|
||||
case NLASTRIP_TYPE_META: /* meta - for now, does the same as transition (is really just an empty container) */
|
||||
case NLASTRIP_TYPE_TRANSITION: /* transition */
|
||||
return nlastrip_get_frame_transition(strip, cframe, mode);
|
||||
|
||||
case NLASTRIP_TYPE_CLIP: /* action-clip (default) */
|
||||
default:
|
||||
return nlastrip_get_frame_actionclip(strip, cframe, mode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* not strip itself! */
|
||||
void free_actionstrip(bActionStrip* strip)
|
||||
/* Non clipped mapping for strip-time <-> global time
|
||||
* mode = eNlaTime_ConvertModesp[] -> NLATIME_CONVERT_*
|
||||
*
|
||||
* Public API method - perform this mapping using the given AnimData block
|
||||
* and perform any necessary sanity checks on the value
|
||||
*/
|
||||
float BKE_nla_tweakedit_remap (AnimData *adt, float cframe, short mode)
|
||||
{
|
||||
if (!strip)
|
||||
NlaStrip *strip;
|
||||
|
||||
/* sanity checks
|
||||
* - obviously we've got to have some starting data
|
||||
* - when not in tweakmode, the active Action does not have any scaling applied :)
|
||||
* - when in tweakmode, if the no-mapping flag is set, do not map
|
||||
*/
|
||||
if ((adt == NULL) || (adt->flag & ADT_NLA_EDIT_ON)==0 || (adt->flag & ADT_NLA_EDIT_NOMAP))
|
||||
return cframe;
|
||||
|
||||
/* if the active-strip info has been stored already, access this, otherwise look this up
|
||||
* and store for (very probable) future usage
|
||||
*/
|
||||
if (adt->actstrip == NULL) {
|
||||
NlaTrack *nlt= BKE_nlatrack_find_active(&adt->nla_tracks);
|
||||
adt->actstrip= BKE_nlastrip_find_active(nlt);
|
||||
}
|
||||
strip= adt->actstrip;
|
||||
|
||||
/* sanity checks
|
||||
* - in rare cases, we may not be able to find this strip for some reason (internal error)
|
||||
* - for now, if the user has defined a curve to control the time, this correction cannot be performed
|
||||
* reliably...
|
||||
*/
|
||||
if ((strip == NULL) || (strip->flag & NLASTRIP_FLAG_USR_TIME))
|
||||
return cframe;
|
||||
|
||||
/* perform the correction now... */
|
||||
return nlastrip_get_frame(strip, cframe, mode);
|
||||
}
|
||||
|
||||
/* *************************************************** */
|
||||
/* NLA API */
|
||||
|
||||
/* List of Strips ------------------------------------ */
|
||||
/* (these functions are used for NLA-Tracks and also for nested/meta-strips) */
|
||||
|
||||
/* Check if there is any space in the given list to add the given strip */
|
||||
short BKE_nlastrips_has_space (ListBase *strips, float start, float end)
|
||||
{
|
||||
NlaStrip *strip;
|
||||
|
||||
/* sanity checks */
|
||||
if ((strips == NULL) || IS_EQ(start, end))
|
||||
return 0;
|
||||
if (start > end) {
|
||||
puts("BKE_nlastrips_has_space() error... start and end arguments swapped");
|
||||
SWAP(float, start, end);
|
||||
}
|
||||
|
||||
/* loop over NLA strips checking for any overlaps with this area... */
|
||||
for (strip= strips->first; strip; strip= strip->next) {
|
||||
/* if start frame of strip is past the target end-frame, that means that
|
||||
* we've gone past the window we need to check for, so things are fine
|
||||
*/
|
||||
if (strip->start > end)
|
||||
return 1;
|
||||
|
||||
/* if the end of the strip is greater than either of the boundaries, the range
|
||||
* must fall within the extents of the strip
|
||||
*/
|
||||
if ((strip->end > start) || (strip->end > end))
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if we are still here, we haven't encountered any overlapping strips */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Rearrange the strips in the track so that they are always in order
|
||||
* (usually only needed after a strip has been moved)
|
||||
*/
|
||||
void BKE_nlastrips_sort_strips (ListBase *strips)
|
||||
{
|
||||
ListBase tmp = {NULL, NULL};
|
||||
NlaStrip *strip, *sstrip, *stripn;
|
||||
|
||||
/* sanity checks */
|
||||
if ELEM(NULL, strips, strips->first)
|
||||
return;
|
||||
|
||||
if (strip->act){
|
||||
strip->act->id.us--;
|
||||
strip->act = NULL;
|
||||
}
|
||||
if (strip->ipo){
|
||||
strip->ipo->id.us--;
|
||||
strip->ipo = NULL;
|
||||
}
|
||||
if (strip->modifiers.first) {
|
||||
BLI_freelistN(&strip->modifiers);
|
||||
|
||||
/* we simply perform insertion sort on this list, since it is assumed that per track,
|
||||
* there are only likely to be at most 5-10 strips
|
||||
*/
|
||||
for (strip= strips->first; strip; strip= stripn) {
|
||||
short not_added = 1;
|
||||
|
||||
stripn= strip->next;
|
||||
|
||||
/* remove this strip from the list, and add it to the new list, searching from the end of
|
||||
* the list, assuming that the lists are in order
|
||||
*/
|
||||
BLI_remlink(strips, strip);
|
||||
|
||||
for (sstrip= tmp.last; sstrip; sstrip= sstrip->prev) {
|
||||
/* check if add after */
|
||||
if (sstrip->end <= strip->start) {
|
||||
BLI_insertlinkafter(&tmp, sstrip, strip);
|
||||
not_added= 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* add before first? */
|
||||
if (not_added)
|
||||
BLI_addhead(&tmp, strip);
|
||||
}
|
||||
|
||||
/* reassign the start and end points of the strips */
|
||||
strips->first= tmp.first;
|
||||
strips->last= tmp.last;
|
||||
}
|
||||
|
||||
void free_nlastrips (ListBase *nlalist)
|
||||
/* Add the given NLA-Strip to the given list of strips, assuming that it
|
||||
* isn't currently a member of another list
|
||||
*/
|
||||
short BKE_nlastrips_add_strip (ListBase *strips, NlaStrip *strip)
|
||||
{
|
||||
bActionStrip *strip;
|
||||
NlaStrip *ns;
|
||||
short not_added = 1;
|
||||
|
||||
/* sanity checks */
|
||||
if ELEM(NULL, strips, strip)
|
||||
return 0;
|
||||
|
||||
/* check if any space to add */
|
||||
if (BKE_nlastrips_has_space(strips, strip->start, strip->end)==0)
|
||||
return 0;
|
||||
|
||||
/* find the right place to add the strip to the nominated track */
|
||||
for (ns= strips->first; ns; ns= ns->next) {
|
||||
/* if current strip occurs after the new strip, add it before */
|
||||
if (ns->start > strip->end) {
|
||||
BLI_insertlinkbefore(strips, ns, strip);
|
||||
not_added= 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (not_added) {
|
||||
/* just add to the end of the list of the strips then... */
|
||||
BLI_addtail(strips, strip);
|
||||
}
|
||||
|
||||
/* added... */
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!nlalist->first)
|
||||
|
||||
/* Meta-Strips ------------------------------------ */
|
||||
|
||||
/* Convert 'islands' (i.e. continuous string of) selected strips to be
|
||||
* contained within 'Meta-Strips' which act as strips which contain strips.
|
||||
* temp: are the meta-strips to be created 'temporary' ones used for transforms?
|
||||
*/
|
||||
void BKE_nlastrips_make_metas (ListBase *strips, short temp)
|
||||
{
|
||||
NlaStrip *mstrip = NULL;
|
||||
NlaStrip *strip, *stripn;
|
||||
|
||||
/* sanity checks */
|
||||
if ELEM(NULL, strips, strips->first)
|
||||
return;
|
||||
|
||||
/* group all continuous chains of selected strips into meta-strips */
|
||||
for (strip= strips->first; strip; strip= stripn) {
|
||||
stripn= strip->next;
|
||||
|
||||
if (strip->flag & NLASTRIP_FLAG_SELECT) {
|
||||
/* if there is an existing meta-strip, add this strip to it, otherwise, create a new one */
|
||||
if (mstrip == NULL) {
|
||||
/* add a new meta-strip, and add it before the current strip that it will replace... */
|
||||
mstrip= MEM_callocN(sizeof(NlaStrip), "Meta-NlaStrip");
|
||||
mstrip->type = NLASTRIP_TYPE_META;
|
||||
BLI_insertlinkbefore(strips, strip, mstrip);
|
||||
|
||||
/* set flags */
|
||||
mstrip->flag = NLASTRIP_FLAG_SELECT;
|
||||
|
||||
/* set temp flag if appropriate (i.e. for transform-type editing) */
|
||||
if (temp)
|
||||
mstrip->flag |= NLASTRIP_FLAG_TEMP_META;
|
||||
|
||||
/* set default repeat/scale values to prevent warnings */
|
||||
mstrip->repeat= mstrip->scale= 1.0f;
|
||||
|
||||
/* make its start frame be set to the start frame of the current strip */
|
||||
mstrip->start= strip->start;
|
||||
}
|
||||
|
||||
/* remove the selected strips from the track, and add to the meta */
|
||||
BLI_remlink(strips, strip);
|
||||
BLI_addtail(&mstrip->strips, strip);
|
||||
|
||||
/* expand the meta's dimensions to include the newly added strip- i.e. its last frame */
|
||||
mstrip->end= strip->end;
|
||||
}
|
||||
else {
|
||||
/* current strip wasn't selected, so the end of 'island' of selected strips has been reached,
|
||||
* so stop adding strips to the current meta
|
||||
*/
|
||||
mstrip= NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Do any specific freeing */
|
||||
for (strip=nlalist->first; strip; strip=strip->next)
|
||||
/* Split a meta-strip into a set of normal strips */
|
||||
void BKE_nlastrips_clear_metastrip (ListBase *strips, NlaStrip *strip)
|
||||
{
|
||||
NlaStrip *cs, *csn;
|
||||
|
||||
/* sanity check */
|
||||
if ELEM(NULL, strips, strip)
|
||||
return;
|
||||
|
||||
/* move each one of the meta-strip's children before the meta-strip
|
||||
* in the list of strips after unlinking them from the meta-strip
|
||||
*/
|
||||
for (cs= strip->strips.first; cs; cs= csn) {
|
||||
csn= cs->next;
|
||||
BLI_remlink(&strip->strips, cs);
|
||||
BLI_insertlinkbefore(strips, strip, cs);
|
||||
}
|
||||
|
||||
/* free the meta-strip now */
|
||||
BLI_freelinkN(strips, strip);
|
||||
}
|
||||
|
||||
/* Remove meta-strips (i.e. flatten the list of strips) from the top-level of the list of strips
|
||||
* sel: only consider selected meta-strips, otherwise all meta-strips are removed
|
||||
* onlyTemp: only remove the 'temporary' meta-strips used for transforms
|
||||
*/
|
||||
void BKE_nlastrips_clear_metas (ListBase *strips, short onlySel, short onlyTemp)
|
||||
{
|
||||
NlaStrip *strip, *stripn;
|
||||
|
||||
/* sanity checks */
|
||||
if ELEM(NULL, strips, strips->first)
|
||||
return;
|
||||
|
||||
/* remove meta-strips fitting the criteria of the arguments */
|
||||
for (strip= strips->first; strip; strip= stripn) {
|
||||
stripn= strip->next;
|
||||
|
||||
/* check if strip is a meta-strip */
|
||||
if (strip->type == NLASTRIP_TYPE_META) {
|
||||
/* if check if selection and 'temporary-only' considerations are met */
|
||||
if ((onlySel==0) || (strip->flag & NLASTRIP_FLAG_SELECT)) {
|
||||
if ((!onlyTemp) || (strip->flag & NLASTRIP_FLAG_TEMP_META)) {
|
||||
BKE_nlastrips_clear_metastrip(strips, strip);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Add the given NLA-Strip to the given Meta-Strip, assuming that the
|
||||
* strip isn't attached to anyy list of strips
|
||||
*/
|
||||
short BKE_nlameta_add_strip (NlaStrip *mstrip, NlaStrip *strip)
|
||||
{
|
||||
/* sanity checks */
|
||||
if ELEM(NULL, mstrip, strip)
|
||||
return 0;
|
||||
|
||||
/* firstly, check if the meta-strip has space for this */
|
||||
if (BKE_nlastrips_has_space(&mstrip->strips, strip->start, strip->end) == 0)
|
||||
return 0;
|
||||
|
||||
/* check if this would need to be added to the ends of the meta,
|
||||
* and subsequently, if the neighbouring strips allow us enough room
|
||||
*/
|
||||
if (strip->start < mstrip->start) {
|
||||
/* check if strip to the left (if it exists) ends before the
|
||||
* start of the strip we're trying to add
|
||||
*/
|
||||
if ((mstrip->prev == NULL) || (mstrip->prev->end <= strip->start)) {
|
||||
/* add strip to start of meta's list, and expand dimensions */
|
||||
BLI_addhead(&mstrip->strips, strip);
|
||||
mstrip->start= strip->start;
|
||||
|
||||
return 1;
|
||||
}
|
||||
else /* failed... no room before */
|
||||
return 0;
|
||||
}
|
||||
else if (strip->end > mstrip->end) {
|
||||
/* check if strip to the right (if it exists) starts before the
|
||||
* end of the strip we're trying to add
|
||||
*/
|
||||
if ((mstrip->next == NULL) || (mstrip->next->start >= strip->end)) {
|
||||
/* add strip to end of meta's list, and expand dimensions */
|
||||
BLI_addtail(&mstrip->strips, strip);
|
||||
mstrip->end= strip->end;
|
||||
|
||||
return 1;
|
||||
}
|
||||
else /* failed... no room after */
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
/* just try to add to the meta-strip (no dimension changes needed) */
|
||||
return BKE_nlastrips_add_strip(&mstrip->strips, strip);
|
||||
}
|
||||
}
|
||||
|
||||
/* Adjust the settings of NLA-Strips contained within a Meta-Strip (recursively),
|
||||
* until the Meta-Strips children all fit within the Meta-Strip's new dimensions
|
||||
*/
|
||||
void BKE_nlameta_flush_transforms (NlaStrip *mstrip)
|
||||
{
|
||||
NlaStrip *strip;
|
||||
float oStart, oEnd, offset;
|
||||
float oLen, nLen;
|
||||
short scaleChanged= 0;
|
||||
|
||||
/* sanity checks
|
||||
* - strip must exist
|
||||
* - strip must be a meta-strip with some contents
|
||||
*/
|
||||
if ELEM(NULL, mstrip, mstrip->strips.first)
|
||||
return;
|
||||
if (mstrip->type != NLASTRIP_TYPE_META)
|
||||
return;
|
||||
|
||||
/* get the original start/end points, and calculate the start-frame offset
|
||||
* - these are simply the start/end frames of the child strips,
|
||||
* since we assume they weren't transformed yet
|
||||
*/
|
||||
oStart= ((NlaStrip *)mstrip->strips.first)->start;
|
||||
oEnd= ((NlaStrip *)mstrip->strips.last)->end;
|
||||
offset= mstrip->start - oStart;
|
||||
|
||||
/* optimisation:
|
||||
* don't flush if nothing changed yet
|
||||
* TODO: maybe we need a flag to say always flush?
|
||||
*/
|
||||
if (IS_EQ(oStart, mstrip->start) && IS_EQ(oEnd, mstrip->end))
|
||||
return;
|
||||
|
||||
/* check if scale changed */
|
||||
oLen = oEnd - oStart;
|
||||
nLen = mstrip->end - mstrip->start;
|
||||
if (IS_EQ(nLen, oLen) == 0)
|
||||
scaleChanged= 1;
|
||||
|
||||
/* for each child-strip, calculate new start/end points based on this new info */
|
||||
for (strip= mstrip->strips.first; strip; strip= strip->next) {
|
||||
if (scaleChanged) {
|
||||
PointerRNA ptr;
|
||||
float p1, p2, nStart, nEnd;
|
||||
|
||||
/* compute positions of endpoints relative to old extents of strip */
|
||||
p1= (strip->start - oStart) / oLen;
|
||||
p2= (strip->end - oStart) / oLen;
|
||||
|
||||
/* compute the new strip endpoints using the proportions */
|
||||
nStart= (p1 * nLen) + mstrip->start;
|
||||
nEnd= (p2 * nLen) + mstrip->start;
|
||||
|
||||
/* firstly, apply the new positions manually, then apply using RNA
|
||||
* - first time is to make sure no truncation errors from one endpoint not being
|
||||
* set yet occur
|
||||
* - second time is to make sure scale is computed properly...
|
||||
*/
|
||||
strip->start= nStart;
|
||||
strip->end= nEnd;
|
||||
|
||||
RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &ptr);
|
||||
RNA_float_set(&ptr, "start_frame", nStart);
|
||||
RNA_float_set(&ptr, "end_frame", nEnd);
|
||||
}
|
||||
else {
|
||||
/* just apply the changes in offset to both ends of the strip */
|
||||
strip->start += offset;
|
||||
strip->end += offset;
|
||||
}
|
||||
|
||||
/* finally, make sure the strip's children (if it is a meta-itself), get updated */
|
||||
BKE_nlameta_flush_transforms(strip);
|
||||
}
|
||||
}
|
||||
|
||||
/* NLA-Tracks ---------------------------------------- */
|
||||
|
||||
/* Find the active NLA-track for the given stack */
|
||||
NlaTrack *BKE_nlatrack_find_active (ListBase *tracks)
|
||||
{
|
||||
NlaTrack *nlt;
|
||||
|
||||
/* sanity check */
|
||||
if ELEM(NULL, tracks, tracks->first)
|
||||
return NULL;
|
||||
|
||||
/* try to find the first active track */
|
||||
for (nlt= tracks->first; nlt; nlt= nlt->next) {
|
||||
if (nlt->flag & NLATRACK_ACTIVE)
|
||||
return nlt;
|
||||
}
|
||||
|
||||
/* none found */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Toggle the 'solo' setting for the given NLA-track, making sure that it is the only one
|
||||
* that has this status in its AnimData block.
|
||||
*/
|
||||
void BKE_nlatrack_solo_toggle (AnimData *adt, NlaTrack *nlt)
|
||||
{
|
||||
NlaTrack *nt;
|
||||
|
||||
/* sanity check */
|
||||
if ELEM(NULL, adt, adt->nla_tracks.first)
|
||||
return;
|
||||
|
||||
/* firstly, make sure 'solo' flag for all tracks is disabled */
|
||||
for (nt= adt->nla_tracks.first; nt; nt= nt->next) {
|
||||
if (nt != nlt)
|
||||
nt->flag &= ~NLATRACK_SOLO;
|
||||
}
|
||||
|
||||
/* now, enable 'solo' for the given track if appropriate */
|
||||
if (nlt) {
|
||||
/* toggle solo status */
|
||||
nlt->flag ^= NLATRACK_SOLO;
|
||||
|
||||
/* set or clear solo-status on AnimData */
|
||||
if (nlt->flag & NLATRACK_SOLO)
|
||||
adt->flag |= ADT_NLA_SOLO_TRACK;
|
||||
else
|
||||
adt->flag &= ~ADT_NLA_SOLO_TRACK;
|
||||
}
|
||||
else
|
||||
adt->flag &= ~ADT_NLA_SOLO_TRACK;
|
||||
}
|
||||
|
||||
/* Make the given NLA-track the active one for the given stack. If no track is provided,
|
||||
* this function can be used to simply deactivate all the NLA tracks in the given stack too.
|
||||
*/
|
||||
void BKE_nlatrack_set_active (ListBase *tracks, NlaTrack *nlt_a)
|
||||
{
|
||||
NlaTrack *nlt;
|
||||
|
||||
/* sanity check */
|
||||
if ELEM(NULL, tracks, tracks->first)
|
||||
return;
|
||||
|
||||
/* deactive all the rest */
|
||||
for (nlt= tracks->first; nlt; nlt= nlt->next)
|
||||
nlt->flag &= ~NLATRACK_ACTIVE;
|
||||
|
||||
/* set the given one as the active one */
|
||||
if (nlt_a)
|
||||
nlt_a->flag |= NLATRACK_ACTIVE;
|
||||
}
|
||||
|
||||
/* Check if there is any space in the given track to add a strip of the given length */
|
||||
short BKE_nlatrack_has_space (NlaTrack *nlt, float start, float end)
|
||||
{
|
||||
/* sanity checks */
|
||||
if ((nlt == NULL) || IS_EQ(start, end))
|
||||
return 0;
|
||||
if (start > end) {
|
||||
puts("BKE_nlatrack_has_space() error... start and end arguments swapped");
|
||||
SWAP(float, start, end);
|
||||
}
|
||||
|
||||
/* check if there's any space left in the track for a strip of the given length */
|
||||
return BKE_nlastrips_has_space(&nlt->strips, start, end);
|
||||
}
|
||||
|
||||
/* Rearrange the strips in the track so that they are always in order
|
||||
* (usually only needed after a strip has been moved)
|
||||
*/
|
||||
void BKE_nlatrack_sort_strips (NlaTrack *nlt)
|
||||
{
|
||||
/* sanity checks */
|
||||
if ELEM(NULL, nlt, nlt->strips.first)
|
||||
return;
|
||||
|
||||
/* sort the strips with a more generic function */
|
||||
BKE_nlastrips_sort_strips(&nlt->strips);
|
||||
}
|
||||
|
||||
/* Add the given NLA-Strip to the given NLA-Track, assuming that it
|
||||
* isn't currently attached to another one
|
||||
*/
|
||||
short BKE_nlatrack_add_strip (NlaTrack *nlt, NlaStrip *strip)
|
||||
{
|
||||
/* sanity checks */
|
||||
if ELEM(NULL, nlt, strip)
|
||||
return 0;
|
||||
|
||||
/* try to add the strip to the track using a more generic function */
|
||||
return BKE_nlastrips_add_strip(&nlt->strips, strip);
|
||||
}
|
||||
|
||||
/* NLA Strips -------------------------------------- */
|
||||
|
||||
/* Find the active NLA-strip within the given track */
|
||||
NlaStrip *BKE_nlastrip_find_active (NlaTrack *nlt)
|
||||
{
|
||||
NlaStrip *strip;
|
||||
|
||||
/* sanity check */
|
||||
if ELEM(NULL, nlt, nlt->strips.first)
|
||||
return NULL;
|
||||
|
||||
/* try to find the first active strip */
|
||||
for (strip= nlt->strips.first; strip; strip= strip->next) {
|
||||
if (strip->flag & NLASTRIP_FLAG_ACTIVE)
|
||||
return strip;
|
||||
}
|
||||
|
||||
/* none found */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Does the given NLA-strip fall within the given bounds (times)? */
|
||||
short BKE_nlastrip_within_bounds (NlaStrip *strip, float min, float max)
|
||||
{
|
||||
const float stripLen= (strip) ? strip->end - strip->start : 0.0f;
|
||||
const float boundsLen= (float)fabs(max - min);
|
||||
|
||||
/* sanity checks */
|
||||
if ((strip == NULL) || IS_EQ(stripLen, 0.0f) || IS_EQ(boundsLen, 0.0f))
|
||||
return 0;
|
||||
|
||||
/* only ok if at least part of the strip is within the bounding window
|
||||
* - first 2 cases cover when the strip length is less than the bounding area
|
||||
* - second 2 cases cover when the strip length is greater than the bounding area
|
||||
*/
|
||||
if ( (stripLen < boundsLen) &&
|
||||
!(IN_RANGE(strip->start, min, max) ||
|
||||
IN_RANGE(strip->end, min, max)) )
|
||||
{
|
||||
free_actionstrip (strip);
|
||||
};
|
||||
|
||||
/* Free the whole list */
|
||||
BLI_freelistN(nlalist);
|
||||
return 0;
|
||||
}
|
||||
if ( (stripLen > boundsLen) &&
|
||||
!(IN_RANGE(min, strip->start, strip->end) ||
|
||||
IN_RANGE(max, strip->start, strip->end)) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* should be ok! */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Is the given NLA-strip the first one to occur for the given AnimData block */
|
||||
// TODO: make this an api method if necesary, but need to add prefix first
|
||||
short nlastrip_is_first (AnimData *adt, NlaStrip *strip)
|
||||
{
|
||||
NlaTrack *nlt;
|
||||
NlaStrip *ns;
|
||||
|
||||
/* sanity checks */
|
||||
if ELEM(NULL, adt, strip)
|
||||
return 0;
|
||||
|
||||
/* check if strip has any strips before it */
|
||||
if (strip->prev)
|
||||
return 0;
|
||||
|
||||
/* check other tracks to see if they have a strip that's earlier */
|
||||
// TODO: or should we check that the strip's track is also the first?
|
||||
for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
|
||||
/* only check the first strip, assuming that they're all in order */
|
||||
ns= nlt->strips.first;
|
||||
if (ns) {
|
||||
if (ns->start < strip->start)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* should be first now */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Animated Strips ------------------------------------------- */
|
||||
|
||||
/* Check if the given NLA-Track has any strips with own F-Curves */
|
||||
short BKE_nlatrack_has_animated_strips (NlaTrack *nlt)
|
||||
{
|
||||
NlaStrip *strip;
|
||||
|
||||
/* sanity checks */
|
||||
if ELEM(NULL, nlt, nlt->strips.first)
|
||||
return 0;
|
||||
|
||||
/* check each strip for F-Curves only (don't care about whether the flags are set) */
|
||||
for (strip= nlt->strips.first; strip; strip= strip->next) {
|
||||
if (strip->fcurves.first)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* none found */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check if given NLA-Tracks have any strips with own F-Curves */
|
||||
short BKE_nlatracks_have_animated_strips (ListBase *tracks)
|
||||
{
|
||||
NlaTrack *nlt;
|
||||
|
||||
/* sanity checks */
|
||||
if ELEM(NULL, tracks, tracks->first)
|
||||
return 0;
|
||||
|
||||
/* check each track, stopping on the first hit */
|
||||
for (nlt= tracks->first; nlt; nlt= nlt->next) {
|
||||
if (BKE_nlatrack_has_animated_strips(nlt))
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* none found */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Validate the NLA-Strips 'control' F-Curves based on the flags set*/
|
||||
void BKE_nlastrip_validate_fcurves (NlaStrip *strip)
|
||||
{
|
||||
FCurve *fcu;
|
||||
|
||||
/* sanity checks */
|
||||
if (strip == NULL)
|
||||
return;
|
||||
|
||||
/* if controlling influence... */
|
||||
if (strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) {
|
||||
/* try to get F-Curve */
|
||||
fcu= list_find_fcurve(&strip->fcurves, "influence", 0);
|
||||
|
||||
/* add one if not found */
|
||||
if (fcu == NULL) {
|
||||
/* make new F-Curve */
|
||||
fcu= MEM_callocN(sizeof(FCurve), "NlaStrip FCurve");
|
||||
BLI_addtail(&strip->fcurves, fcu);
|
||||
|
||||
/* set default flags */
|
||||
fcu->flag = (FCURVE_VISIBLE|FCURVE_AUTO_HANDLES|FCURVE_SELECTED);
|
||||
|
||||
/* store path - make copy, and store that */
|
||||
fcu->rna_path= BLI_strdupn("influence", 9);
|
||||
|
||||
// TODO: insert a few keyframes to ensure default behaviour?
|
||||
}
|
||||
}
|
||||
|
||||
/* if controlling time... */
|
||||
if (strip->flag & NLASTRIP_FLAG_USR_TIME) {
|
||||
/* try to get F-Curve */
|
||||
fcu= list_find_fcurve(&strip->fcurves, "strip_time", 0);
|
||||
|
||||
/* add one if not found */
|
||||
if (fcu == NULL) {
|
||||
/* make new F-Curve */
|
||||
fcu= MEM_callocN(sizeof(FCurve), "NlaStrip FCurve");
|
||||
BLI_addtail(&strip->fcurves, fcu);
|
||||
|
||||
/* set default flags */
|
||||
fcu->flag = (FCURVE_VISIBLE|FCURVE_AUTO_HANDLES|FCURVE_SELECTED);
|
||||
|
||||
/* store path - make copy, and store that */
|
||||
fcu->rna_path= BLI_strdupn("strip_time", 10);
|
||||
|
||||
// TODO: insert a few keyframes to ensure default behaviour?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Sanity Validation ------------------------------------ */
|
||||
|
||||
/* Find (and set) a unique name for a strip from the whole AnimData block
|
||||
* Uses a similar method to the BLI method, but is implemented differently
|
||||
* as we need to ensure that the name is unique over several lists of tracks,
|
||||
* not just a single track.
|
||||
*/
|
||||
void BKE_nlastrip_validate_name (AnimData *adt, NlaStrip *strip)
|
||||
{
|
||||
GHash *gh;
|
||||
NlaStrip *tstrip;
|
||||
NlaTrack *nlt;
|
||||
|
||||
/* sanity checks */
|
||||
if ELEM(NULL, adt, strip)
|
||||
return;
|
||||
|
||||
/* give strip a default name if none already */
|
||||
if (strip->name[0]==0) {
|
||||
switch (strip->type) {
|
||||
case NLASTRIP_TYPE_CLIP: /* act-clip */
|
||||
sprintf(strip->name, "Act: %s", (strip->act)?(strip->act->id.name+2):("<None>"));
|
||||
break;
|
||||
case NLASTRIP_TYPE_TRANSITION: /* transition */
|
||||
sprintf(strip->name, "Transition");
|
||||
break;
|
||||
case NLASTRIP_TYPE_META: /* meta */
|
||||
sprintf(strip->name, "Meta");
|
||||
break;
|
||||
default:
|
||||
sprintf(strip->name, "NLA Strip");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* build a hash-table of all the strips in the tracks
|
||||
* - this is easier than iterating over all the tracks+strips hierarchy everytime
|
||||
* (and probably faster)
|
||||
*/
|
||||
gh= BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp);
|
||||
|
||||
for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
|
||||
for (tstrip= nlt->strips.first; tstrip; tstrip= tstrip->next) {
|
||||
/* don't add the strip of interest */
|
||||
if (tstrip == strip)
|
||||
continue;
|
||||
|
||||
/* use the name of the strip as the key, and the strip as the value, since we're mostly interested in the keys */
|
||||
BLI_ghash_insert(gh, tstrip->name, tstrip);
|
||||
}
|
||||
}
|
||||
|
||||
/* if the hash-table has a match for this name, try other names...
|
||||
* - in an extreme case, it might not be able to find a name, but then everything else in Blender would fail too :)
|
||||
*/
|
||||
if (BLI_ghash_haskey(gh, strip->name)) {
|
||||
char tempname[128];
|
||||
int number = 1;
|
||||
char *dot;
|
||||
|
||||
/* Strip off the suffix */
|
||||
dot = strchr(strip->name, '.');
|
||||
if (dot) *dot=0;
|
||||
|
||||
/* Try different possibilities */
|
||||
for (number = 1; number <= 999; number++) {
|
||||
/* assemble alternative name */
|
||||
BLI_snprintf(tempname, 128, "%s%c%03d", strip->name, ".", number);
|
||||
|
||||
/* if hash doesn't have this, set it */
|
||||
if (BLI_ghash_haskey(gh, tempname) == 0) {
|
||||
BLI_strncpy(strip->name, tempname, sizeof(strip->name));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* free the hash... */
|
||||
BLI_ghash_free(gh, NULL, NULL);
|
||||
}
|
||||
|
||||
/* ---- */
|
||||
|
||||
/* Determine auto-blending for the given strip */
|
||||
void BKE_nlastrip_validate_autoblends (NlaTrack *nlt, NlaStrip *nls)
|
||||
{
|
||||
NlaTrack *track;
|
||||
NlaStrip *strip;
|
||||
//float *ps=NULL, *pe=NULL;
|
||||
//float *ns=NULL, *ne=NULL;
|
||||
|
||||
/* sanity checks */
|
||||
if ELEM(NULL, nls, nlt)
|
||||
return;
|
||||
if ((nlt->prev == NULL) && (nlt->next == NULL))
|
||||
return;
|
||||
if ((nls->flag & NLASTRIP_FLAG_AUTO_BLENDS)==0)
|
||||
return;
|
||||
|
||||
/* get test ranges */
|
||||
if (nlt->prev) {
|
||||
/* find strips that overlap over the start/end of the given strip,
|
||||
* but which don't cover the entire length
|
||||
*/
|
||||
track= nlt->prev;
|
||||
for (strip= track->strips.first; strip; strip= strip->next) {
|
||||
|
||||
}
|
||||
}
|
||||
if (nlt->next) {
|
||||
/* find strips that overlap over the start/end of the given strip,
|
||||
* but which don't cover the entire length
|
||||
*/
|
||||
track= nlt->next;
|
||||
for (strip= track->strips.first; strip; strip= strip->next) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Ensure that auto-blending and other settings are set correctly */
|
||||
void BKE_nla_validate_state (AnimData *adt)
|
||||
{
|
||||
NlaStrip *strip;
|
||||
NlaTrack *nlt;
|
||||
|
||||
/* sanity checks */
|
||||
if ELEM(NULL, adt, adt->nla_tracks.first)
|
||||
return;
|
||||
|
||||
/* adjust blending values for auto-blending */
|
||||
for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
|
||||
for (strip= nlt->strips.first; strip; strip= strip->next) {
|
||||
BKE_nlastrip_validate_autoblends(nlt, strip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Core Tools ------------------------------------------- */
|
||||
|
||||
/* For the given AnimData block, add the active action to the NLA
|
||||
* stack (i.e. 'push-down' action). The UI should only allow this
|
||||
* for normal editing only (i.e. not in editmode for some strip's action),
|
||||
* so no checks for this are performed.
|
||||
*/
|
||||
// TODO: maybe we should have checks for this too...
|
||||
void BKE_nla_action_pushdown (AnimData *adt)
|
||||
{
|
||||
NlaStrip *strip;
|
||||
|
||||
/* sanity checks */
|
||||
// TODO: need to report the error for this
|
||||
if ELEM(NULL, adt, adt->action)
|
||||
return;
|
||||
|
||||
/* if the action is empty, we also shouldn't try to add to stack,
|
||||
* as that will cause us grief down the track
|
||||
*/
|
||||
// TODO: what about modifiers?
|
||||
if (action_has_motion(adt->action) == 0) {
|
||||
printf("BKE_nla_action_pushdown(): action has no data \n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* add a new NLA strip to the track, which references the active action */
|
||||
strip= add_nlastrip_to_stack(adt, adt->action);
|
||||
|
||||
/* do other necessary work on strip */
|
||||
if (strip) {
|
||||
/* clear reference to action now that we've pushed it onto the stack */
|
||||
adt->action->id.us--;
|
||||
adt->action= NULL;
|
||||
|
||||
/* if the strip is the first one in the track it lives in, check if there
|
||||
* are strips in any other tracks that may be before this, and set the extend
|
||||
* mode accordingly
|
||||
*/
|
||||
if (nlastrip_is_first(adt, strip) == 0) {
|
||||
/* not first, so extend mode can only be NLASTRIP_EXTEND_HOLD_FORWARD not NLASTRIP_EXTEND_HOLD,
|
||||
* so that it doesn't override strips in previous tracks
|
||||
*/
|
||||
// FIXME: this needs to be more automated, since user can rearrange strips
|
||||
strip->extendmode= NLASTRIP_EXTEND_HOLD_FORWARD;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Find the active strip + track combo, and set them up as the tweaking track,
|
||||
* and return if successful or not.
|
||||
*/
|
||||
short BKE_nla_tweakmode_enter (AnimData *adt)
|
||||
{
|
||||
NlaTrack *nlt, *activeTrack=NULL;
|
||||
NlaStrip *strip, *activeStrip=NULL;
|
||||
|
||||
/* verify that data is valid */
|
||||
if ELEM(NULL, adt, adt->nla_tracks.first)
|
||||
return 0;
|
||||
|
||||
/* if block is already in tweakmode, just leave, but we should report
|
||||
* that this block is in tweakmode (as our returncode)
|
||||
*/
|
||||
if (adt->flag & ADT_NLA_EDIT_ON)
|
||||
return 1;
|
||||
|
||||
/* go over the tracks, finding the active one, and its active strip
|
||||
* - if we cannot find both, then there's nothing to do
|
||||
*/
|
||||
for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
|
||||
/* check if active */
|
||||
if (nlt->flag & NLATRACK_ACTIVE) {
|
||||
/* store reference to this active track */
|
||||
activeTrack= nlt;
|
||||
|
||||
/* now try to find active strip */
|
||||
activeStrip= BKE_nlastrip_find_active(nlt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ELEM3(NULL, activeTrack, activeStrip, activeStrip->act) {
|
||||
printf("NLA tweakmode enter - neither active requirement found \n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* go over all the tracks up to the active one, tagging each strip that uses the same
|
||||
* action as the active strip, but leaving everything else alone
|
||||
*/
|
||||
for (nlt= activeTrack->prev; nlt; nlt= nlt->prev) {
|
||||
for (strip= nlt->strips.first; strip; strip= strip->next) {
|
||||
if (strip->act == activeStrip->act)
|
||||
strip->flag |= NLASTRIP_FLAG_TWEAKUSER;
|
||||
else
|
||||
strip->flag &= ~NLASTRIP_FLAG_TWEAKUSER;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* go over all the tracks after AND INCLUDING the active one, tagging them as being disabled
|
||||
* - the active track needs to also be tagged, otherwise, it'll overlap with the tweaks going on
|
||||
*/
|
||||
for (nlt= activeTrack; nlt; nlt= nlt->next)
|
||||
nlt->flag |= NLATRACK_DISABLED;
|
||||
|
||||
/* handle AnimData level changes:
|
||||
* - 'real' active action to temp storage (no need to change user-counts)
|
||||
* - action of active strip set to be the 'active action', and have its usercount incremented
|
||||
* - editing-flag for this AnimData block should also get turned on (for more efficient restoring)
|
||||
* - take note of the active strip for mapping-correction of keyframes in the action being edited
|
||||
*/
|
||||
adt->tmpact= adt->action;
|
||||
adt->action= activeStrip->act;
|
||||
adt->actstrip= activeStrip;
|
||||
id_us_plus(&activeStrip->act->id);
|
||||
adt->flag |= ADT_NLA_EDIT_ON;
|
||||
|
||||
/* done! */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Exit tweakmode for this AnimData block */
|
||||
void BKE_nla_tweakmode_exit (AnimData *adt)
|
||||
{
|
||||
NlaStrip *strip;
|
||||
NlaTrack *nlt;
|
||||
|
||||
/* verify that data is valid */
|
||||
if ELEM(NULL, adt, adt->nla_tracks.first)
|
||||
return;
|
||||
|
||||
/* hopefully the flag is correct - skip if not on */
|
||||
if ((adt->flag & ADT_NLA_EDIT_ON) == 0)
|
||||
return;
|
||||
|
||||
// TODO: need to sync the user-strip with the new state of the action!
|
||||
|
||||
/* for all Tracks, clear the 'disabled' flag
|
||||
* for all Strips, clear the 'tweak-user' flag
|
||||
*/
|
||||
for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
|
||||
nlt->flag &= ~NLATRACK_DISABLED;
|
||||
|
||||
for (strip= nlt->strips.first; strip; strip= strip->next)
|
||||
strip->flag &= ~NLASTRIP_FLAG_TWEAKUSER;
|
||||
}
|
||||
|
||||
/* handle AnimData level changes:
|
||||
* - 'temporary' active action needs its usercount decreased, since we're removing this reference
|
||||
* - 'real' active action is restored from storage
|
||||
* - storage pointer gets cleared (to avoid having bad notes hanging around)
|
||||
* - editing-flag for this AnimData block should also get turned off
|
||||
* - clear pointer to active strip
|
||||
*/
|
||||
if (adt->action) adt->action->id.us--;
|
||||
adt->action= adt->tmpact;
|
||||
adt->tmpact= NULL;
|
||||
adt->actstrip= NULL;
|
||||
adt->flag &= ~ADT_NLA_EDIT_ON;
|
||||
}
|
||||
|
||||
/* *************************************************** */
|
||||
|
||||
@@ -1198,18 +1198,12 @@ Object *copy_object(Object *ob)
|
||||
armature_rebuild_pose(obn, obn->data);
|
||||
}
|
||||
copy_defgroups(&obn->defbase, &ob->defbase);
|
||||
#if 0 // XXX old animation system
|
||||
copy_nlastrips(&obn->nlastrips, &ob->nlastrips);
|
||||
#endif // XXX old animation system
|
||||
copy_constraints(&obn->constraints, &ob->constraints);
|
||||
|
||||
/* increase user numbers */
|
||||
id_us_plus((ID *)obn->data);
|
||||
#if 0 // XXX old animation system
|
||||
id_us_plus((ID *)obn->ipo);
|
||||
id_us_plus((ID *)obn->action);
|
||||
#endif // XXX old animation system
|
||||
id_us_plus((ID *)obn->dup_group);
|
||||
// FIXME: add this for animdata too...
|
||||
|
||||
for(a=0; a<obn->totcol; a++) id_us_plus((ID *)obn->mat[a]);
|
||||
|
||||
@@ -1575,14 +1569,14 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[][4])
|
||||
}
|
||||
/* catch exceptions: curve paths used as a duplicator */
|
||||
else if(enable_cu_speed) {
|
||||
ctime= bsystem_time(scene, ob, (float)scene->r.cfra, 0.0);
|
||||
|
||||
#if 0 // XXX old animation system
|
||||
if(calc_ipo_spec(cu->ipo, CU_SPEED, &ctime)==0) {
|
||||
ctime /= cu->pathlen;
|
||||
CLAMP(ctime, 0.0, 1.0);
|
||||
}
|
||||
#endif // XXX old animation system
|
||||
/* ctime is now a proper var setting of Curve which gets set by Animato like any other var that's animated,
|
||||
* but this will only work if it actually is animated...
|
||||
*
|
||||
* we firstly calculate the modulus of cu->ctime/cu->pathlen to clamp ctime within the 0.0 to 1.0 times pathlen
|
||||
* range, then divide this (the modulus) by pathlen to get a value between 0.0 and 1.0
|
||||
*/
|
||||
ctime= fmod(cu->ctime, cu->pathlen) / cu->pathlen;
|
||||
CLAMP(ctime, 0.0, 1.0);
|
||||
}
|
||||
else {
|
||||
ctime= scene->r.cfra - give_timeoffset(ob);
|
||||
|
||||
85
source/blender/blenkernel/nla_private.h
Normal file
85
source/blender/blenkernel/nla_private.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* $Id: BKE_nla.h 20999 2009-06-19 04:45:56Z aligorith $
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): Joshua Leung (full recode)
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#ifndef NLA_PRIVATE
|
||||
#define NLA_PRIVATE
|
||||
|
||||
/* --------------- NLA Evaluation DataTypes ----------------------- */
|
||||
|
||||
/* used for list of strips to accumulate at current time */
|
||||
typedef struct NlaEvalStrip {
|
||||
struct NlaEvalStrip *next, *prev;
|
||||
|
||||
NlaTrack *track; /* track that this strip belongs to */
|
||||
NlaStrip *strip; /* strip that's being used */
|
||||
|
||||
short track_index; /* the index of the track within the list */
|
||||
short strip_mode; /* which end of the strip are we looking at */
|
||||
|
||||
float strip_time; /* time at which which strip is being evaluated */
|
||||
} NlaEvalStrip;
|
||||
|
||||
/* NlaEvalStrip->strip_mode */
|
||||
enum {
|
||||
/* standard evaluation */
|
||||
NES_TIME_BEFORE = -1,
|
||||
NES_TIME_WITHIN,
|
||||
NES_TIME_AFTER,
|
||||
|
||||
/* transition-strip evaluations */
|
||||
NES_TIME_TRANSITION_START,
|
||||
NES_TIME_TRANSITION_END,
|
||||
} eNlaEvalStrip_StripMode;
|
||||
|
||||
|
||||
/* temp channel for accumulating data from NLA (avoids needing to clear all values first) */
|
||||
// TODO: maybe this will be used as the 'cache' stuff needed for editable values too?
|
||||
typedef struct NlaEvalChannel {
|
||||
struct NlaEvalChannel *next, *prev;
|
||||
|
||||
PointerRNA ptr; /* pointer to struct containing property to use */
|
||||
PropertyRNA *prop; /* RNA-property type to use (should be in the struct given) */
|
||||
int index; /* array index (where applicable) */
|
||||
|
||||
float value; /* value of this channel */
|
||||
} NlaEvalChannel;
|
||||
|
||||
/* --------------- NLA Functions (not to be used as a proper API) ----------------------- */
|
||||
|
||||
/* convert from strip time <-> global time */
|
||||
float nlastrip_get_frame(NlaStrip *strip, float cframe, short mode);
|
||||
|
||||
/* --------------- NLA Evaluation (very-private stuff) ----------------------- */
|
||||
/* these functions are only defined here to avoid problems with the order in which they get defined... */
|
||||
|
||||
NlaEvalStrip *nlastrips_ctime_get_strip(ListBase *list, ListBase *strips, short index, float ctime);
|
||||
void nlastrip_evaluate(PointerRNA *ptr, ListBase *channels, ListBase *modifiers, NlaEvalStrip *nes);
|
||||
void nladata_flush_channels(ListBase *channels);
|
||||
|
||||
#endif // NLA_PRIVATE
|
||||
@@ -1667,10 +1667,26 @@ static void lib_link_constraint_channels(FileData *fd, ID *id, ListBase *chanbas
|
||||
|
||||
/* Data Linking ----------------------------- */
|
||||
|
||||
static void lib_link_fmodifiers(FileData *fd, ID *id, ListBase *list)
|
||||
{
|
||||
FModifier *fcm;
|
||||
|
||||
for (fcm= list->first; fcm; fcm= fcm->next) {
|
||||
/* data for specific modifiers */
|
||||
switch (fcm->type) {
|
||||
case FMODIFIER_TYPE_PYTHON:
|
||||
{
|
||||
FMod_Python *data= (FMod_Python *)fcm->data;
|
||||
data->script = newlibadr(fd, id->lib, data->script);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void lib_link_fcurves(FileData *fd, ID *id, ListBase *list)
|
||||
{
|
||||
FCurve *fcu;
|
||||
FModifier *fcm;
|
||||
|
||||
/* relink ID-block references... */
|
||||
for (fcu= list->first; fcu; fcu= fcu->next) {
|
||||
@@ -1684,16 +1700,45 @@ static void lib_link_fcurves(FileData *fd, ID *id, ListBase *list)
|
||||
}
|
||||
|
||||
/* modifiers */
|
||||
for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next) {
|
||||
/* data for specific modifiers */
|
||||
switch (fcm->type) {
|
||||
case FMODIFIER_TYPE_PYTHON:
|
||||
{
|
||||
FMod_Python *data= (FMod_Python *)fcm->data;
|
||||
data->script = newlibadr(fd, id->lib, data->script);
|
||||
}
|
||||
break;
|
||||
lib_link_fmodifiers(fd, id, &fcu->modifiers);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* NOTE: this assumes that link_list has already been called on the list */
|
||||
static void direct_link_fmodifiers(FileData *fd, ListBase *list)
|
||||
{
|
||||
FModifier *fcm;
|
||||
|
||||
for (fcm= list->first; fcm; fcm= fcm->next) {
|
||||
/* relink general data */
|
||||
fcm->data = newdataadr(fd, fcm->data);
|
||||
fcm->edata= NULL;
|
||||
|
||||
/* do relinking of data for specific types */
|
||||
switch (fcm->type) {
|
||||
case FMODIFIER_TYPE_GENERATOR:
|
||||
{
|
||||
FMod_Generator *data= (FMod_Generator *)fcm->data;
|
||||
|
||||
data->coefficients= newdataadr(fd, data->coefficients);
|
||||
}
|
||||
break;
|
||||
case FMODIFIER_TYPE_ENVELOPE:
|
||||
{
|
||||
FMod_Envelope *data= (FMod_Envelope *)fcm->data;
|
||||
|
||||
data->data= newdataadr(fd, data->data);
|
||||
}
|
||||
break;
|
||||
case FMODIFIER_TYPE_PYTHON:
|
||||
{
|
||||
FMod_Python *data= (FMod_Python *)fcm->data;
|
||||
|
||||
data->prop = newdataadr(fd, data->prop);
|
||||
IDP_DirectLinkProperty(data->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1702,7 +1747,6 @@ static void lib_link_fcurves(FileData *fd, ID *id, ListBase *list)
|
||||
static void direct_link_fcurves(FileData *fd, ListBase *list)
|
||||
{
|
||||
FCurve *fcu;
|
||||
FModifier *fcm;
|
||||
|
||||
/* link F-Curve data to F-Curve again (non ID-libs) */
|
||||
for (fcu= list->first; fcu; fcu= fcu->next) {
|
||||
@@ -1730,37 +1774,7 @@ static void direct_link_fcurves(FileData *fd, ListBase *list)
|
||||
|
||||
/* modifiers */
|
||||
link_list(fd, &fcu->modifiers);
|
||||
for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next) {
|
||||
/* relink general data */
|
||||
fcm->data = newdataadr(fd, fcm->data);
|
||||
fcm->edata= NULL;
|
||||
|
||||
/* do relinking of data for specific types */
|
||||
switch (fcm->type) {
|
||||
case FMODIFIER_TYPE_GENERATOR:
|
||||
{
|
||||
FMod_Generator *data= (FMod_Generator *)fcm->data;
|
||||
|
||||
data->coefficients= newdataadr(fd, data->coefficients);
|
||||
}
|
||||
break;
|
||||
case FMODIFIER_TYPE_ENVELOPE:
|
||||
{
|
||||
FMod_Envelope *data= (FMod_Envelope *)fcm->data;
|
||||
|
||||
data->data= newdataadr(fd, data->data);
|
||||
}
|
||||
break;
|
||||
case FMODIFIER_TYPE_PYTHON:
|
||||
{
|
||||
FMod_Python *data= (FMod_Python *)fcm->data;
|
||||
|
||||
data->prop = newdataadr(fd, data->prop);
|
||||
IDP_DirectLinkProperty(data->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
direct_link_fmodifiers(fd, &fcu->modifiers);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1812,6 +1826,65 @@ static void direct_link_action(FileData *fd, bAction *act)
|
||||
}
|
||||
}
|
||||
|
||||
static void lib_link_nladata_strips(FileData *fd, ID *id, ListBase *list)
|
||||
{
|
||||
NlaStrip *strip;
|
||||
|
||||
for (strip= list->first; strip; strip= strip->next) {
|
||||
/* check strip's children */
|
||||
lib_link_nladata_strips(fd, id, &strip->strips);
|
||||
|
||||
/* reassign the counted-reference to action */
|
||||
strip->act = newlibadr_us(fd, id->lib, strip->act);
|
||||
}
|
||||
}
|
||||
|
||||
static void lib_link_nladata(FileData *fd, ID *id, ListBase *list)
|
||||
{
|
||||
NlaTrack *nlt;
|
||||
|
||||
/* we only care about the NLA strips inside the tracks */
|
||||
for (nlt= list->first; nlt; nlt= nlt->next) {
|
||||
lib_link_nladata_strips(fd, id, &nlt->strips);
|
||||
}
|
||||
}
|
||||
|
||||
/* This handles Animato NLA-Strips linking
|
||||
* NOTE: this assumes that link_list has already been called on the list
|
||||
*/
|
||||
static void direct_link_nladata_strips(FileData *fd, ListBase *list)
|
||||
{
|
||||
NlaStrip *strip;
|
||||
|
||||
for (strip= list->first; strip; strip= strip->next) {
|
||||
/* strip's child strips */
|
||||
link_list(fd, &strip->strips);
|
||||
direct_link_nladata_strips(fd, &strip->strips);
|
||||
|
||||
/* strip's F-Curves */
|
||||
link_list(fd, &strip->fcurves);
|
||||
direct_link_fcurves(fd, &strip->fcurves);
|
||||
|
||||
/* strip's F-Modifiers */
|
||||
link_list(fd, &strip->modifiers);
|
||||
direct_link_fcurves(fd, &strip->modifiers);
|
||||
}
|
||||
}
|
||||
|
||||
/* NOTE: this assumes that link_list has already been called on the list */
|
||||
static void direct_link_nladata(FileData *fd, ListBase *list)
|
||||
{
|
||||
NlaTrack *nlt;
|
||||
|
||||
for (nlt= list->first; nlt; nlt= nlt->next) {
|
||||
/* relink list of strips */
|
||||
link_list(fd, &nlt->strips);
|
||||
|
||||
/* relink strip data */
|
||||
direct_link_nladata_strips(fd, &nlt->strips);
|
||||
}
|
||||
}
|
||||
|
||||
/* ------- */
|
||||
|
||||
static void lib_link_keyingsets(FileData *fd, ID *id, ListBase *list)
|
||||
@@ -1854,6 +1927,7 @@ static void lib_link_animdata(FileData *fd, ID *id, AnimData *adt)
|
||||
|
||||
/* link action data */
|
||||
adt->action= newlibadr_us(fd, id->lib, adt->action);
|
||||
adt->tmpact= newlibadr_us(fd, id->lib, adt->tmpact);
|
||||
|
||||
/* link drivers */
|
||||
lib_link_fcurves(fd, id, &adt->drivers);
|
||||
@@ -1861,7 +1935,7 @@ static void lib_link_animdata(FileData *fd, ID *id, AnimData *adt)
|
||||
/* overrides don't have lib-link for now, so no need to do anything */
|
||||
|
||||
/* link NLA-data */
|
||||
// TODO...
|
||||
lib_link_nladata(fd, id, &adt->nla_tracks);
|
||||
}
|
||||
|
||||
static void direct_link_animdata(FileData *fd, AnimData *adt)
|
||||
@@ -1878,7 +1952,12 @@ static void direct_link_animdata(FileData *fd, AnimData *adt)
|
||||
// TODO...
|
||||
|
||||
/* link NLA-data */
|
||||
// TODO...
|
||||
link_list(fd, &adt->nla_tracks);
|
||||
direct_link_nladata(fd, &adt->nla_tracks);
|
||||
|
||||
/* clear temp pointers that may have been set... */
|
||||
// TODO: it's probably only a small cost to reload this anyway...
|
||||
adt->actstrip= NULL;
|
||||
}
|
||||
|
||||
/* ************ READ NODE TREE *************** */
|
||||
@@ -4708,6 +4787,11 @@ static void direct_link_screen(FileData *fd, bScreen *sc)
|
||||
sipo->ads= newdataadr(fd, sipo->ads);
|
||||
sipo->ghostCurves.first= sipo->ghostCurves.last= NULL;
|
||||
}
|
||||
else if (sl->spacetype==SPACE_NLA) {
|
||||
SpaceNla *snla= (SpaceNla*)sl;
|
||||
|
||||
snla->ads= newdataadr(fd, snla->ads);
|
||||
}
|
||||
else if (sl->spacetype==SPACE_OUTLINER) {
|
||||
SpaceOops *soops= (SpaceOops*) sl;
|
||||
|
||||
@@ -9150,7 +9234,14 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
|
||||
if(ts->normalsize == 0.0 || !ts->uv_selectmode || ts->vgroup_weight == 0.0) {
|
||||
ts->normalsize= 0.1f;
|
||||
ts->selectmode= SCE_SELECT_VERTEX;
|
||||
|
||||
/* autokeying - setting should be taken from the user-prefs
|
||||
* but the userprefs version may not have correct flags set
|
||||
* (i.e. will result in blank box when enabled)
|
||||
*/
|
||||
ts->autokey_mode= U.autokey_mode;
|
||||
if (ts->autokey_mode == 0)
|
||||
ts->autokey_mode= 2; /* 'add/replace' but not on */
|
||||
ts->uv_selectmode= UV_SELECT_VERTEX;
|
||||
ts->vgroup_weight= 1.0f;
|
||||
}
|
||||
@@ -9485,12 +9576,27 @@ static void expand_keyingsets(FileData *fd, Main *mainvar, ListBase *list)
|
||||
}
|
||||
}
|
||||
|
||||
static void expand_animdata_nlastrips(FileData *fd, Main *mainvar, ListBase *list)
|
||||
{
|
||||
NlaStrip *strip;
|
||||
|
||||
for (strip= list->first; strip; strip= strip->next) {
|
||||
/* check child strips */
|
||||
expand_animdata_nlastrips(fd, mainvar, &strip->strips);
|
||||
|
||||
/* relink referenced action */
|
||||
expand_doit(fd, mainvar, strip->act);
|
||||
}
|
||||
}
|
||||
|
||||
static void expand_animdata(FileData *fd, Main *mainvar, AnimData *adt)
|
||||
{
|
||||
FCurve *fcd;
|
||||
NlaTrack *nlt;
|
||||
|
||||
/* own action */
|
||||
expand_doit(fd, mainvar, adt->action);
|
||||
expand_doit(fd, mainvar, adt->tmpact);
|
||||
|
||||
/* drivers - assume that these F-Curves have driver data to be in this list... */
|
||||
for (fcd= adt->drivers.first; fcd; fcd= fcd->next) {
|
||||
@@ -9500,6 +9606,10 @@ static void expand_animdata(FileData *fd, Main *mainvar, AnimData *adt)
|
||||
for (dtar= driver->targets.first; dtar; dtar= dtar->next)
|
||||
expand_doit(fd, mainvar, dtar->id);
|
||||
}
|
||||
|
||||
/* nla-data - referenced actions */
|
||||
for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next)
|
||||
expand_animdata_nlastrips(fd, mainvar, &nlt->strips);
|
||||
}
|
||||
|
||||
static void expand_particlesettings(FileData *fd, Main *mainvar, ParticleSettings *part)
|
||||
|
||||
@@ -781,10 +781,59 @@ static void write_actuators(WriteData *wd, ListBase *lb)
|
||||
}
|
||||
}
|
||||
|
||||
static void write_fmodifiers(WriteData *wd, ListBase *fmodifiers)
|
||||
{
|
||||
FModifier *fcm;
|
||||
|
||||
/* Modifiers */
|
||||
for (fcm= fmodifiers->first; fcm; fcm= fcm->next) {
|
||||
FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
|
||||
|
||||
/* Write the specific data */
|
||||
if (fmi && fcm->data) {
|
||||
/* firstly, just write the plain fmi->data struct */
|
||||
writestruct(wd, DATA, fmi->structName, 1, fcm->data);
|
||||
|
||||
/* do any modifier specific stuff */
|
||||
switch (fcm->type) {
|
||||
case FMODIFIER_TYPE_GENERATOR:
|
||||
{
|
||||
FMod_Generator *data= (FMod_Generator *)fcm->data;
|
||||
|
||||
/* write coefficients array */
|
||||
if (data->coefficients)
|
||||
writedata(wd, DATA, sizeof(float)*(data->arraysize), data->coefficients);
|
||||
}
|
||||
break;
|
||||
case FMODIFIER_TYPE_ENVELOPE:
|
||||
{
|
||||
FMod_Envelope *data= (FMod_Envelope *)fcm->data;
|
||||
|
||||
/* write envelope data */
|
||||
if (data->data)
|
||||
writedata(wd, DATA, sizeof(FCM_EnvelopeData)*(data->totvert), data->data);
|
||||
}
|
||||
break;
|
||||
case FMODIFIER_TYPE_PYTHON:
|
||||
{
|
||||
FMod_Python *data = (FMod_Python *)fcm->data;
|
||||
|
||||
/* Write ID Properties -- and copy this comment EXACTLY for easy finding
|
||||
of library blocks that implement this.*/
|
||||
IDP_WriteProperty(data->prop, wd);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write the modifier */
|
||||
writestruct(wd, DATA, "FModifier", 1, fcm);
|
||||
}
|
||||
}
|
||||
|
||||
static void write_fcurves(WriteData *wd, ListBase *fcurves)
|
||||
{
|
||||
FCurve *fcu;
|
||||
FModifier *fcm;
|
||||
|
||||
for (fcu=fcurves->first; fcu; fcu=fcu->next) {
|
||||
/* F-Curve */
|
||||
@@ -815,50 +864,8 @@ static void write_fcurves(WriteData *wd, ListBase *fcurves)
|
||||
}
|
||||
}
|
||||
|
||||
/* Modifiers */
|
||||
for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next) {
|
||||
FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
|
||||
|
||||
/* Write the specific data */
|
||||
if (fmi && fcm->data) {
|
||||
/* firstly, just write the plain fmi->data struct */
|
||||
writestruct(wd, DATA, fmi->structName, 1, fcm->data);
|
||||
|
||||
/* do any modifier specific stuff */
|
||||
switch (fcm->type) {
|
||||
case FMODIFIER_TYPE_GENERATOR:
|
||||
{
|
||||
FMod_Generator *data= (FMod_Generator *)fcm->data;
|
||||
|
||||
/* write coefficients array */
|
||||
if (data->coefficients)
|
||||
writedata(wd, DATA, sizeof(float)*(data->arraysize), data->coefficients);
|
||||
}
|
||||
break;
|
||||
case FMODIFIER_TYPE_ENVELOPE:
|
||||
{
|
||||
FMod_Envelope *data= (FMod_Envelope *)fcm->data;
|
||||
|
||||
/* write envelope data */
|
||||
if (data->data)
|
||||
writedata(wd, DATA, sizeof(FCM_EnvelopeData)*(data->totvert), data->data);
|
||||
}
|
||||
break;
|
||||
case FMODIFIER_TYPE_PYTHON:
|
||||
{
|
||||
FMod_Python *data = (FMod_Python *)fcm->data;
|
||||
|
||||
/* Write ID Properties -- and copy this comment EXACTLY for easy finding
|
||||
of library blocks that implement this.*/
|
||||
IDP_WriteProperty(data->prop, wd);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write the modifier */
|
||||
writestruct(wd, DATA, "FModifier", 1, fcm);
|
||||
}
|
||||
/* write F-Modifiers */
|
||||
write_fmodifiers(wd, &fcu->modifiers);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -909,6 +916,37 @@ static void write_keyingsets(WriteData *wd, ListBase *list)
|
||||
}
|
||||
}
|
||||
|
||||
static void write_nlastrips(WriteData *wd, ListBase *strips)
|
||||
{
|
||||
NlaStrip *strip;
|
||||
|
||||
for (strip= strips->first; strip; strip= strip->next) {
|
||||
/* write the strip first */
|
||||
writestruct(wd, DATA, "NlaStrip", 1, strip);
|
||||
|
||||
/* write the strip's F-Curves and modifiers */
|
||||
write_fcurves(wd, &strip->fcurves);
|
||||
write_fmodifiers(wd, &strip->modifiers);
|
||||
|
||||
/* write the strip's children */
|
||||
write_nlastrips(wd, &strip->strips);
|
||||
}
|
||||
}
|
||||
|
||||
static void write_nladata(WriteData *wd, ListBase *nlabase)
|
||||
{
|
||||
NlaTrack *nlt;
|
||||
|
||||
/* write all the tracks */
|
||||
for (nlt= nlabase->first; nlt; nlt= nlt->next) {
|
||||
/* write the track first */
|
||||
writestruct(wd, DATA, "NlaTrack", 1, nlt);
|
||||
|
||||
/* write the track's strips */
|
||||
write_nlastrips(wd, &nlt->strips);
|
||||
}
|
||||
}
|
||||
|
||||
static void write_animdata(WriteData *wd, AnimData *adt)
|
||||
{
|
||||
AnimOverride *aor;
|
||||
@@ -920,14 +958,17 @@ static void write_animdata(WriteData *wd, AnimData *adt)
|
||||
write_fcurves(wd, &adt->drivers);
|
||||
|
||||
/* write overrides */
|
||||
// FIXME: are these needed?
|
||||
for (aor= adt->overrides.first; aor; aor= aor->next) {
|
||||
/* overrides consist of base data + rna_path */
|
||||
writestruct(wd, DATA, "AnimOverride", 1, aor);
|
||||
writedata(wd, DATA, strlen(aor->rna_path)+1, aor->rna_path);
|
||||
}
|
||||
|
||||
// TODO write the remaps (if they are needed)
|
||||
|
||||
/* write NLA data */
|
||||
// XXX todo...
|
||||
write_nladata(wd, &adt->nla_tracks);
|
||||
}
|
||||
|
||||
static void write_constraints(WriteData *wd, ListBase *conlist)
|
||||
@@ -1899,7 +1940,10 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
|
||||
writestruct(wd, DATA, "SpaceSound", 1, sl);
|
||||
}
|
||||
else if(sl->spacetype==SPACE_NLA){
|
||||
writestruct(wd, DATA, "SpaceNla", 1, sl);
|
||||
SpaceNla *snla= (SpaceNla *)sl;
|
||||
|
||||
writestruct(wd, DATA, "SpaceNla", 1, snla);
|
||||
if(snla->ads) writestruct(wd, DATA, "bDopeSheet", 1, snla->ads);
|
||||
}
|
||||
else if(sl->spacetype==SPACE_TIME){
|
||||
writestruct(wd, DATA, "SpaceTime", 1, sl);
|
||||
|
||||
@@ -63,9 +63,10 @@
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_define.h"
|
||||
|
||||
#include "BKE_animsys.h"
|
||||
#include "BKE_action.h"
|
||||
#include "BKE_depsgraph.h"
|
||||
#include "BKE_ipo.h"
|
||||
#include "BKE_fcurve.h"
|
||||
#include "BKE_key.h"
|
||||
#include "BKE_material.h"
|
||||
#include "BKE_object.h"
|
||||
@@ -87,43 +88,16 @@
|
||||
/* ************************************************************************** */
|
||||
/* 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 */
|
||||
void ANIM_set_active_channel (void *data, short datatype, int filter, void *channel_data, short channel_type)
|
||||
void ANIM_set_active_channel (bAnimContext *ac, void *data, short datatype, int filter, void *channel_data, short channel_type)
|
||||
{
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
bAnimListElem *ale;
|
||||
|
||||
/* try to build list of filtered items */
|
||||
// XXX we don't need/supply animcontext for now, since in this case, there's nothing really essential there that isn't already covered
|
||||
ANIM_animdata_filter(NULL, &anim_data, filter, data, datatype);
|
||||
ANIM_animdata_filter(ac, &anim_data, filter, data, datatype);
|
||||
if (anim_data.first == NULL)
|
||||
return;
|
||||
|
||||
@@ -149,11 +123,18 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
/* set active flag */
|
||||
if (channel_data) {
|
||||
if (channel_data != NULL) {
|
||||
switch (channel_type) {
|
||||
case ANIMTYPE_GROUP:
|
||||
{
|
||||
@@ -167,6 +148,12 @@ 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;
|
||||
nlt->flag |= NLATRACK_ACTIVE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,6 +204,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 +254,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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -273,6 +272,47 @@ void ANIM_deselect_anim_channels (void *data, short datatype, short test, short
|
||||
/* ************************************************************************** */
|
||||
/* OPERATORS */
|
||||
|
||||
/* ****************** Operator Utilities ********************************** */
|
||||
|
||||
/* poll callback for being in an Animation Editor channels list region */
|
||||
int animedit_poll_channels_active (bContext *C)
|
||||
{
|
||||
ScrArea *sa= CTX_wm_area(C);
|
||||
|
||||
/* channels region test */
|
||||
// TODO: could enhance with actually testing if channels region?
|
||||
if (ELEM(NULL, sa, CTX_wm_region(C)))
|
||||
return 0;
|
||||
/* animation editor test */
|
||||
if (ELEM3(sa->spacetype, SPACE_ACTION, SPACE_IPO, SPACE_NLA) == 0)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* poll callback for Animation Editor channels list region + not in NLA-tweakmode for NLA */
|
||||
int animedit_poll_channels_nla_tweakmode_off (bContext *C)
|
||||
{
|
||||
ScrArea *sa= CTX_wm_area(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
|
||||
/* channels region test */
|
||||
// TODO: could enhance with actually testing if channels region?
|
||||
if (ELEM(NULL, sa, CTX_wm_region(C)))
|
||||
return 0;
|
||||
/* animation editor test */
|
||||
if (ELEM3(sa->spacetype, SPACE_ACTION, SPACE_IPO, SPACE_NLA) == 0)
|
||||
return 0;
|
||||
|
||||
/* NLA TweakMode test */
|
||||
if (sa->spacetype == SPACE_NLA) {
|
||||
if ((scene == NULL) || (scene->flag & SCE_NLA_EDIT_ON))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ****************** Rearrange Channels Operator ******************* */
|
||||
/* This operator only works for Action Editor mode for now, as having it elsewhere makes things difficult */
|
||||
|
||||
@@ -575,8 +615,8 @@ static int animchannels_rearrange_exec(bContext *C, wmOperator *op)
|
||||
mode= RNA_enum_get(op->ptr, "direction");
|
||||
rearrange_action_channels(&ac, mode);
|
||||
|
||||
/* set notifier tha things have changed */
|
||||
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_CHANNELS);
|
||||
/* send notifier that things have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_EDIT, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
@@ -652,6 +692,121 @@ void ANIM_OT_channels_move_bottom (wmOperatorType *ot)
|
||||
|
||||
#endif // XXX old animation system - needs to be updated for new system...
|
||||
|
||||
/* ******************** Delete Channel Operator *********************** */
|
||||
|
||||
static int animchannels_delete_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
bAnimContext ac;
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
bAnimListElem *ale;
|
||||
int filter;
|
||||
|
||||
/* get editor data */
|
||||
if (ANIM_animdata_get_context(C, &ac) == 0)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
/* cannot delete in shapekey */
|
||||
if (ac.datatype == ANIMCONT_SHAPEKEY)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
|
||||
/* do groups only first (unless in Drivers mode, where there are none) */
|
||||
if (ac.datatype != ANIMCONT_DRIVERS) {
|
||||
/* filter data */
|
||||
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_CHANNELS | ANIMFILTER_FOREDIT);
|
||||
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
|
||||
|
||||
/* delete selected groups and their associated channels */
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
/* only groups - don't check other types yet, since they may no-longer exist */
|
||||
if (ale->type == ANIMTYPE_GROUP) {
|
||||
bActionGroup *agrp= (bActionGroup *)ale->data;
|
||||
AnimData *adt= BKE_animdata_from_id(ale->id);
|
||||
FCurve *fcu, *fcn;
|
||||
|
||||
/* skip this group if no AnimData available, as we can't safely remove the F-Curves */
|
||||
if (adt == NULL)
|
||||
continue;
|
||||
|
||||
/* delete all of the Group's F-Curves, but no others */
|
||||
for (fcu= agrp->channels.first; fcu && fcu->grp==agrp; fcu= fcn) {
|
||||
fcn= fcu->next;
|
||||
|
||||
/* remove from group and action, then free */
|
||||
action_groups_remove_channel(adt->action, fcu);
|
||||
free_fcurve(fcu);
|
||||
}
|
||||
|
||||
/* free the group itself */
|
||||
if (adt->action)
|
||||
BLI_freelinkN(&adt->action->groups, agrp);
|
||||
else
|
||||
MEM_freeN(agrp);
|
||||
}
|
||||
}
|
||||
|
||||
/* cleanup */
|
||||
BLI_freelistN(&anim_data);
|
||||
}
|
||||
|
||||
/* now do F-Curves */
|
||||
if (ac.datatype != ANIMCONT_GPENCIL) {
|
||||
/* filter data */
|
||||
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT);
|
||||
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
|
||||
|
||||
/* delete selected F-Curves */
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
/* only F-Curves, and only if we can identify its parent */
|
||||
if (ale->type == ANIMTYPE_FCURVE) {
|
||||
AnimData *adt= BKE_animdata_from_id(ale->id);
|
||||
FCurve *fcu= (FCurve *)ale->data;
|
||||
|
||||
/* if no AnimData, we've got nowhere to remove the F-Curve from */
|
||||
if (adt == NULL)
|
||||
continue;
|
||||
|
||||
/* remove from whatever list it came from
|
||||
* - Action Group
|
||||
* - Action
|
||||
* - Drivers
|
||||
* - TODO... some others?
|
||||
*/
|
||||
if (fcu->grp)
|
||||
action_groups_remove_channel(adt->action, fcu);
|
||||
else if (adt->action)
|
||||
BLI_remlink(&adt->action->curves, fcu);
|
||||
else if (ac.datatype == ANIMCONT_DRIVERS)
|
||||
BLI_remlink(&adt->drivers, fcu);
|
||||
|
||||
/* free the F-Curve itself */
|
||||
free_fcurve(fcu);
|
||||
}
|
||||
}
|
||||
|
||||
/* cleanup */
|
||||
BLI_freelistN(&anim_data);
|
||||
}
|
||||
|
||||
/* send notifier that things have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_EDIT, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void ANIM_OT_channels_delete (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Delete Channels";
|
||||
ot->idname= "ANIM_OT_channels_delete";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= animchannels_delete_exec;
|
||||
ot->poll= animedit_poll_channels_active;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/* ******************** Toggle Channel Visibility Operator *********************** */
|
||||
|
||||
@@ -668,7 +823,7 @@ static int animchannels_visibility_toggle_exec(bContext *C, wmOperator *op)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
/* filter data */
|
||||
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_CURVESONLY);
|
||||
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL);
|
||||
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
|
||||
|
||||
/* See if we should be making showing all selected or hiding */
|
||||
@@ -676,21 +831,35 @@ static int animchannels_visibility_toggle_exec(bContext *C, wmOperator *op)
|
||||
if (vis == ACHANNEL_SETFLAG_CLEAR)
|
||||
break;
|
||||
|
||||
if (ale->flag & FCURVE_VISIBLE)
|
||||
if ((ale->type == ANIMTYPE_FCURVE) && (ale->flag & FCURVE_VISIBLE))
|
||||
vis= ACHANNEL_SETFLAG_CLEAR;
|
||||
else if ((ale->type == ANIMTYPE_GROUP) && !(ale->flag & AGRP_NOTVISIBLE))
|
||||
vis= ACHANNEL_SETFLAG_CLEAR;
|
||||
}
|
||||
|
||||
/* Now set the flags */
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
FCurve *fcu= (FCurve *)ale->data;
|
||||
ACHANNEL_SET_FLAG(fcu, vis, FCURVE_VISIBLE);
|
||||
switch (ale->type) {
|
||||
case ANIMTYPE_FCURVE: /* F-Curve */
|
||||
{
|
||||
FCurve *fcu= (FCurve *)ale->data;
|
||||
ACHANNEL_SET_FLAG(fcu, vis, FCURVE_VISIBLE);
|
||||
}
|
||||
break;
|
||||
case ANIMTYPE_GROUP: /* Group */
|
||||
{
|
||||
bActionGroup *agrp= (bActionGroup *)ale->data;
|
||||
ACHANNEL_SET_FLAG_NEG(agrp, vis, AGRP_NOTVISIBLE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* cleanup */
|
||||
BLI_freelistN(&anim_data);
|
||||
|
||||
/* set notifier tha things have changed */
|
||||
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_CHANNELS);
|
||||
/* send notifier that things have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_EDIT, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
@@ -889,6 +1058,12 @@ static void setflag_anim_channels (bAnimContext *ac, short setting, short mode,
|
||||
case ACHANNEL_SETTING_EXPAND:
|
||||
ACHANNEL_SET_FLAG(agrp, mode, AGRP_EXPANDED);
|
||||
break;
|
||||
case ACHANNEL_SETTING_MUTE:
|
||||
ACHANNEL_SET_FLAG(agrp, mode, AGRP_MUTED);
|
||||
break;
|
||||
case ACHANNEL_SETTING_VISIBLE:
|
||||
ACHANNEL_SET_FLAG_NEG(agrp, mode, AGRP_NOTVISIBLE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -947,8 +1122,8 @@ static int animchannels_setflag_exec(bContext *C, wmOperator *op)
|
||||
/* modify setting */
|
||||
setflag_anim_channels(&ac, setting, mode, 1);
|
||||
|
||||
/* set notifier tha things have changed */
|
||||
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_CHANNELS);
|
||||
/* send notifier that things have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_EDIT, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
@@ -963,7 +1138,7 @@ void ANIM_OT_channels_setting_enable (wmOperatorType *ot)
|
||||
/* api callbacks */
|
||||
ot->invoke= WM_menu_invoke;
|
||||
ot->exec= animchannels_setflag_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= animedit_poll_channels_active;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -984,7 +1159,7 @@ void ANIM_OT_channels_setting_disable (wmOperatorType *ot)
|
||||
/* api callbacks */
|
||||
ot->invoke= WM_menu_invoke;
|
||||
ot->exec= animchannels_setflag_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= animedit_poll_channels_active;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -1005,7 +1180,7 @@ void ANIM_OT_channels_setting_toggle (wmOperatorType *ot)
|
||||
/* api callbacks */
|
||||
ot->invoke= WM_menu_invoke;
|
||||
ot->exec= animchannels_setflag_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= animedit_poll_channels_active;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -1026,7 +1201,7 @@ void ANIM_OT_channels_editable_toggle (wmOperatorType *ot)
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= animchannels_setflag_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= animedit_poll_channels_active;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -1056,8 +1231,8 @@ static int animchannels_expand_exec (bContext *C, wmOperator *op)
|
||||
/* modify setting */
|
||||
setflag_anim_channels(&ac, ACHANNEL_SETTING_EXPAND, ACHANNEL_SETFLAG_ADD, onlysel);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_CHANNELS);
|
||||
/* send notifier that things have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_EDIT, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
@@ -1070,7 +1245,7 @@ void ANIM_OT_channels_expand (wmOperatorType *ot)
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= animchannels_expand_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= animedit_poll_channels_active;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -1097,8 +1272,8 @@ static int animchannels_collapse_exec (bContext *C, wmOperator *op)
|
||||
/* modify setting */
|
||||
setflag_anim_channels(&ac, ACHANNEL_SETTING_EXPAND, ACHANNEL_SETFLAG_CLEAR, onlysel);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_CHANNELS);
|
||||
/* send notifier that things have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_EDIT, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
@@ -1111,7 +1286,7 @@ void ANIM_OT_channels_collapse (wmOperatorType *ot)
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= animchannels_collapse_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= animedit_poll_channels_active;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -1136,8 +1311,8 @@ static int animchannels_deselectall_exec(bContext *C, wmOperator *op)
|
||||
else
|
||||
ANIM_deselect_anim_channels(ac.data, ac.datatype, 1, ACHANNEL_SETFLAG_ADD);
|
||||
|
||||
/* set notifier tha things have changed */
|
||||
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_CHANNELS);
|
||||
/* send notifier that things have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_SELECT, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
@@ -1150,7 +1325,7 @@ void ANIM_OT_channels_select_all_toggle (wmOperatorType *ot)
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= animchannels_deselectall_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= animedit_poll_channels_nla_tweakmode_off;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -1218,6 +1393,14 @@ static void borderselect_anim_channels (bAnimContext *ac, rcti *rect, short sele
|
||||
ACHANNEL_SET_FLAG(gpl, selectmode, GP_LAYER_SELECT);
|
||||
}
|
||||
break;
|
||||
|
||||
case ANIMTYPE_NLATRACK: /* nla-track */
|
||||
{
|
||||
NlaTrack *nlt= (NlaTrack *)ale->data;
|
||||
|
||||
ACHANNEL_SET_FLAG(nlt, selectmode, NLATRACK_SELECTED);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1257,6 +1440,9 @@ static int animchannels_borderselect_exec(bContext *C, wmOperator *op)
|
||||
/* apply borderselect animation channels */
|
||||
borderselect_anim_channels(&ac, &rect, selectmode);
|
||||
|
||||
/* send notifier that things have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_SELECT, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
@@ -1271,7 +1457,7 @@ void ANIM_OT_channels_select_border(wmOperatorType *ot)
|
||||
ot->exec= animchannels_borderselect_exec;
|
||||
ot->modal= WM_border_select_modal;
|
||||
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= animedit_poll_channels_nla_tweakmode_off;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -1291,11 +1477,12 @@ void ANIM_OT_channels_select_border(wmOperatorType *ot)
|
||||
* NOTE: eventually, this should probably be phased out when many of these things are replaced with buttons
|
||||
*/
|
||||
|
||||
static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, short selectmode)
|
||||
static int mouse_anim_channels (bAnimContext *ac, float x, int channel_index, short selectmode)
|
||||
{
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
bAnimListElem *ale;
|
||||
int filter;
|
||||
int notifierFlags = 0;
|
||||
|
||||
/* get the channel that was clicked on */
|
||||
/* filter channels */
|
||||
@@ -1309,7 +1496,7 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s
|
||||
printf("Error: animation channel (index = %d) not found in mouse_anim_channels() \n", channel_index);
|
||||
|
||||
BLI_freelistN(&anim_data);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* selectmode -1 is a special case for ActionGroups only, which selects all of the channels underneath it only... */
|
||||
@@ -1317,7 +1504,7 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s
|
||||
if ((selectmode == -1) && (ale->type != ANIMTYPE_GROUP)) {
|
||||
/* normal channels should not behave normally in this case */
|
||||
BLI_freelistN(&anim_data);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* action to take depends on what channel we've got */
|
||||
@@ -1329,6 +1516,8 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s
|
||||
if (x < 16) {
|
||||
/* toggle expand */
|
||||
sce->flag ^= SCE_DS_COLLAPSED;
|
||||
|
||||
notifierFlags |= ND_ANIMCHAN_EDIT;
|
||||
}
|
||||
else {
|
||||
/* set selection status */
|
||||
@@ -1339,6 +1528,8 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s
|
||||
else {
|
||||
sce->flag |= SCE_DS_SELECTED;
|
||||
}
|
||||
|
||||
notifierFlags |= ND_ANIMCHAN_SELECT;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1352,6 +1543,8 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s
|
||||
if (x < 16) {
|
||||
/* toggle expand */
|
||||
ob->nlaflag ^= OB_ADS_COLLAPSED; // XXX
|
||||
|
||||
notifierFlags |= ND_ANIMCHAN_EDIT;
|
||||
}
|
||||
else {
|
||||
/* set selection status */
|
||||
@@ -1376,6 +1569,8 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s
|
||||
|
||||
/* xxx should be ED_base_object_activate(), but we need context pointer for that... */
|
||||
//set_active_base(base);
|
||||
|
||||
notifierFlags |= ND_ANIMCHAN_SELECT;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1383,18 +1578,21 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s
|
||||
{
|
||||
bAction *act= (bAction *)ale->data;
|
||||
act->flag ^= ACT_COLLAPSED;
|
||||
notifierFlags |= ND_ANIMCHAN_EDIT;
|
||||
}
|
||||
break;
|
||||
case ANIMTYPE_FILLDRIVERS:
|
||||
{
|
||||
AnimData *adt= (AnimData* )ale->data;
|
||||
adt->flag ^= ADT_DRIVERS_COLLAPSED;
|
||||
notifierFlags |= ND_ANIMCHAN_EDIT;
|
||||
}
|
||||
break;
|
||||
case ANIMTYPE_FILLMATD:
|
||||
{
|
||||
Object *ob= (Object *)ale->data;
|
||||
ob->nlaflag ^= OB_ADS_SHOWMATS; // XXX
|
||||
notifierFlags |= ND_ANIMCHAN_EDIT;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1402,36 +1600,42 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s
|
||||
{
|
||||
Material *ma= (Material *)ale->data;
|
||||
ma->flag ^= MA_DS_EXPAND;
|
||||
notifierFlags |= ND_ANIMCHAN_EDIT;
|
||||
}
|
||||
break;
|
||||
case ANIMTYPE_DSLAM:
|
||||
{
|
||||
Lamp *la= (Lamp *)ale->data;
|
||||
la->flag ^= LA_DS_EXPAND;
|
||||
notifierFlags |= ND_ANIMCHAN_EDIT;
|
||||
}
|
||||
break;
|
||||
case ANIMTYPE_DSCAM:
|
||||
{
|
||||
Camera *ca= (Camera *)ale->data;
|
||||
ca->flag ^= CAM_DS_EXPAND;
|
||||
notifierFlags |= ND_ANIMCHAN_EDIT;
|
||||
}
|
||||
break;
|
||||
case ANIMTYPE_DSCUR:
|
||||
{
|
||||
Curve *cu= (Curve *)ale->data;
|
||||
cu->flag ^= CU_DS_EXPAND;
|
||||
notifierFlags |= ND_ANIMCHAN_EDIT;
|
||||
}
|
||||
break;
|
||||
case ANIMTYPE_DSSKEY:
|
||||
{
|
||||
Key *key= (Key *)ale->data;
|
||||
key->flag ^= KEYBLOCK_DS_EXPAND;
|
||||
notifierFlags |= ND_ANIMCHAN_EDIT;
|
||||
}
|
||||
break;
|
||||
case ANIMTYPE_DSWOR:
|
||||
{
|
||||
World *wo= (World *)ale->data;
|
||||
wo->flag ^= WO_DS_EXPAND;
|
||||
notifierFlags |= ND_ANIMCHAN_EDIT;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1443,10 +1647,22 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s
|
||||
if ((x < (offset+17)) && (agrp->channels.first)) {
|
||||
/* toggle expand */
|
||||
agrp->flag ^= AGRP_EXPANDED;
|
||||
notifierFlags |= ND_ANIMCHAN_EDIT;
|
||||
}
|
||||
else if ((x < (offset+32)) && (ac->spacetype==SPACE_IPO)) {
|
||||
/* toggle visibility (of grouped F-Curves in Graph editor) */
|
||||
agrp->flag ^= AGRP_NOTVISIBLE;
|
||||
notifierFlags |= ND_ANIMCHAN_EDIT;
|
||||
}
|
||||
else if (x >= (ACHANNEL_NAMEWIDTH-ACHANNEL_BUTTON_WIDTH)) {
|
||||
/* toggle protection/locking */
|
||||
agrp->flag ^= AGRP_PROTECTED;
|
||||
notifierFlags |= ND_ANIMCHAN_EDIT;
|
||||
}
|
||||
else if (x >= (ACHANNEL_NAMEWIDTH-2*ACHANNEL_BUTTON_WIDTH)) {
|
||||
/* toggle mute */
|
||||
agrp->flag ^= AGRP_MUTED;
|
||||
notifierFlags |= ND_ANIMCHAN_EDIT;
|
||||
}
|
||||
else {
|
||||
/* select/deselect group */
|
||||
@@ -1474,7 +1690,9 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s
|
||||
|
||||
/* if group is selected now, make group the 'active' one in the visible list */
|
||||
if (agrp->flag & AGRP_SELECTED)
|
||||
ANIM_set_active_channel(ac->data, ac->datatype, filter, agrp, ANIMTYPE_GROUP);
|
||||
ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, agrp, ANIMTYPE_GROUP);
|
||||
|
||||
notifierFlags |= ND_ANIMCHAN_SELECT;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1495,16 +1713,20 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s
|
||||
|
||||
if (x >= (ACHANNEL_NAMEWIDTH-ACHANNEL_BUTTON_WIDTH)) {
|
||||
/* toggle protection (only if there's a toggle there) */
|
||||
if (fcu->bezt)
|
||||
if (fcu->bezt) {
|
||||
fcu->flag ^= FCURVE_PROTECTED;
|
||||
notifierFlags |= ND_ANIMCHAN_EDIT;
|
||||
}
|
||||
}
|
||||
else if (x >= (ACHANNEL_NAMEWIDTH-2*ACHANNEL_BUTTON_WIDTH)) {
|
||||
/* toggle mute */
|
||||
fcu->flag ^= FCURVE_MUTED;
|
||||
notifierFlags |= ND_ANIMCHAN_EDIT;
|
||||
}
|
||||
else if ((x < (offset+17)) && (ac->spacetype==SPACE_IPO)) {
|
||||
/* toggle visibility */
|
||||
fcu->flag ^= FCURVE_VISIBLE;
|
||||
notifierFlags |= ND_ANIMCHAN_EDIT;
|
||||
}
|
||||
else {
|
||||
/* select/deselect */
|
||||
@@ -1520,7 +1742,9 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s
|
||||
|
||||
/* if F-Curve is selected now, make F-Curve the 'active' one in the visible list */
|
||||
if (fcu->flag & FCURVE_SELECTED)
|
||||
ANIM_set_active_channel(ac->data, ac->datatype, filter, fcu, ANIMTYPE_FCURVE);
|
||||
ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ANIMTYPE_FCURVE);
|
||||
|
||||
notifierFlags |= ND_ANIMCHAN_SELECT;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1530,6 +1754,8 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s
|
||||
|
||||
/* toggle expand */
|
||||
gpd->flag ^= GP_DATA_EXPAND;
|
||||
|
||||
notifierFlags |= ND_ANIMCHAN_EDIT;
|
||||
}
|
||||
break;
|
||||
case ANIMTYPE_GPLAYER:
|
||||
@@ -1568,6 +1794,9 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s
|
||||
|
||||
/* free channels */
|
||||
BLI_freelistN(&anim_data);
|
||||
|
||||
/* return notifier flags */
|
||||
return notifierFlags;
|
||||
}
|
||||
|
||||
/* ------------------- */
|
||||
@@ -1580,6 +1809,7 @@ static int animchannels_mouseclick_invoke(bContext *C, wmOperator *op, wmEvent *
|
||||
ARegion *ar;
|
||||
View2D *v2d;
|
||||
int mval[2], channel_index;
|
||||
int notifierFlags = 0;
|
||||
short selectmode;
|
||||
float x, y;
|
||||
|
||||
@@ -1614,10 +1844,10 @@ static int animchannels_mouseclick_invoke(bContext *C, wmOperator *op, wmEvent *
|
||||
UI_view2d_listview_view_to_cell(v2d, ACHANNEL_NAMEWIDTH, ACHANNEL_STEP, 0, (float)ACHANNEL_HEIGHT_HALF, x, y, NULL, &channel_index);
|
||||
|
||||
/* handle mouse-click in the relevant channel then */
|
||||
mouse_anim_channels(&ac, x, channel_index, selectmode);
|
||||
notifierFlags= mouse_anim_channels(&ac, x, channel_index, selectmode);
|
||||
|
||||
/* set notifier tha things have changed */
|
||||
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_CHANNELS);
|
||||
/* set notifier that things have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|notifierFlags, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
@@ -1630,7 +1860,7 @@ void ANIM_OT_channels_click (wmOperatorType *ot)
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke= animchannels_mouseclick_invoke;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= animedit_poll_channels_active;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -1653,6 +1883,8 @@ void ED_operatortypes_animchannels(void)
|
||||
WM_operatortype_append(ANIM_OT_channels_setting_disable);
|
||||
WM_operatortype_append(ANIM_OT_channels_setting_toggle);
|
||||
|
||||
WM_operatortype_append(ANIM_OT_channels_delete);
|
||||
|
||||
// XXX does this need to be a separate operator?
|
||||
WM_operatortype_append(ANIM_OT_channels_editable_toggle);
|
||||
|
||||
@@ -1686,6 +1918,10 @@ void ED_keymap_animchannels(wmWindowManager *wm)
|
||||
/* borderselect */
|
||||
WM_keymap_add_item(keymap, "ANIM_OT_channels_select_border", BKEY, KM_PRESS, 0, 0);
|
||||
|
||||
/* delete */
|
||||
WM_keymap_add_item(keymap, "ANIM_OT_channels_delete", XKEY, KM_PRESS, 0, 0);
|
||||
WM_keymap_add_item(keymap, "ANIM_OT_channels_delete", DELKEY, KM_PRESS, 0, 0);
|
||||
|
||||
/* settings */
|
||||
WM_keymap_add_item(keymap, "ANIM_OT_channels_setting_toggle", WKEY, KM_PRESS, KM_SHIFT, 0);
|
||||
WM_keymap_add_item(keymap, "ANIM_OT_channels_setting_enable", WKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0);
|
||||
|
||||
@@ -77,72 +77,6 @@ void ED_anim_object_flush_update(const bContext *C, Object *ob)
|
||||
}
|
||||
|
||||
|
||||
/* **************************** animation tool notifiers ******************************** */
|
||||
|
||||
/* Send notifiers on behalf of animation editing tools, based on various context info
|
||||
* - data_changed: eAnimData_Changed
|
||||
*/
|
||||
void ANIM_animdata_send_notifiers (bContext *C, bAnimContext *ac, short data_changed)
|
||||
{
|
||||
/* types of notifiers to send, depends on the editor context */
|
||||
switch (ac->datatype) {
|
||||
case ANIMCONT_DOPESHEET: /* dopesheet */
|
||||
case ANIMCONT_FCURVES: /* fcurve editor */
|
||||
case ANIMCONT_DRIVERS: /* drivers editor */ // XXX probably this will need separate handling, since these are part of dependency system
|
||||
{
|
||||
/* what action was taken */
|
||||
switch (data_changed) {
|
||||
case ANIM_CHANGED_KEYFRAMES_VALUES:
|
||||
/* keyframe values changed, so transform may have changed */
|
||||
// XXX what about other cases? maybe we need general ND_KEYFRAMES or ND_ANIMATION?
|
||||
WM_event_add_notifier(C, NC_OBJECT|ND_KEYS|ND_TRANSFORM, NULL);
|
||||
break;
|
||||
case ANIM_CHANGED_KEYFRAMES_SELECT:
|
||||
WM_event_add_notifier(C, NC_OBJECT|ND_KEYS, NULL);
|
||||
break;
|
||||
case ANIM_CHANGED_CHANNELS:
|
||||
// XXX err... check available datatypes in dopesheet first?
|
||||
// FIXME: this currently doesn't work (to update own view)
|
||||
WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE|ND_OB_SELECT, ac->scene);
|
||||
WM_event_add_notifier(C, NC_OBJECT|ND_BONE_ACTIVE|ND_BONE_SELECT, NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
// XXX for now, at least update own editor!
|
||||
ED_area_tag_redraw(CTX_wm_area(C));
|
||||
}
|
||||
break;
|
||||
|
||||
case ANIMCONT_ACTION: /* action editor */
|
||||
{
|
||||
Object *obact= CTX_data_active_object(C);
|
||||
|
||||
switch (data_changed) {
|
||||
case ANIM_CHANGED_KEYFRAMES_VALUES:
|
||||
/* keyframe values changed, so transform may have changed */
|
||||
// XXX what about other cases? maybe we need general ND_KEYFRAMES or ND_ANIMATION?
|
||||
WM_event_add_notifier(C, NC_OBJECT|ND_KEYS|ND_TRANSFORM, obact);
|
||||
break;
|
||||
case ANIM_CHANGED_KEYFRAMES_SELECT:
|
||||
WM_event_add_notifier(C, NC_OBJECT|ND_KEYS, obact);
|
||||
break;
|
||||
case ANIM_CHANGED_CHANNELS:
|
||||
// XXX err... check available datatypes in dopesheet first?
|
||||
// FIXME: this currently doesn't work (to update own view)
|
||||
WM_event_add_notifier(C, NC_OBJECT|ND_BONE_ACTIVE|ND_BONE_SELECT, obact);
|
||||
break;
|
||||
}
|
||||
|
||||
// XXX for now, at least update own editor!
|
||||
ED_area_tag_redraw(CTX_wm_area(C));
|
||||
}
|
||||
break;
|
||||
|
||||
default: /* some other data... just update area for now */
|
||||
ED_area_tag_redraw(CTX_wm_area(C));
|
||||
}
|
||||
}
|
||||
|
||||
/* **************************** pose <-> action syncing ******************************** */
|
||||
/* Summary of what needs to be synced between poses and actions:
|
||||
* 1) Flags
|
||||
@@ -152,6 +86,10 @@ void ANIM_animdata_send_notifiers (bContext *C, bAnimContext *ac, short data_cha
|
||||
* 3) Grouping (only for pose to action for now)
|
||||
*/
|
||||
|
||||
/* XXX OBSOLETE CODE WARNING:
|
||||
* With the Animato system, the code below is somewhat obsolete now...
|
||||
*/
|
||||
|
||||
/* Notifier from Action/Dopesheet (this may be extended to include other things such as Python...)
|
||||
* Channels in action changed, so update pose channels/groups to reflect changes.
|
||||
*
|
||||
|
||||
@@ -43,10 +43,12 @@
|
||||
|
||||
#include "BLI_blenlib.h"
|
||||
|
||||
#include "BKE_animsys.h"
|
||||
#include "BKE_action.h"
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_fcurve.h"
|
||||
#include "BKE_nla.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_screen.h"
|
||||
#include "BKE_utildefines.h"
|
||||
@@ -232,37 +234,16 @@ void ANIM_draw_previewrange (const bContext *C, View2D *v2d)
|
||||
/* *************************************************** */
|
||||
/* NLA-MAPPING UTILITIES (required for drawing and also editing keyframes) */
|
||||
|
||||
/* Obtain the Object providing NLA-scaling for the given channel (if applicable) */
|
||||
Object *ANIM_nla_mapping_get(bAnimContext *ac, bAnimListElem *ale)
|
||||
/* Obtain the AnimData block providing NLA-mapping for the given channel (if applicable) */
|
||||
AnimData *ANIM_nla_mapping_get(bAnimContext *ac, bAnimListElem *ale)
|
||||
{
|
||||
/* sanity checks */
|
||||
if (ac == NULL)
|
||||
return NULL;
|
||||
|
||||
/* handling depends on the type of animation-context we've got */
|
||||
if (ac->datatype == ANIMCONT_ACTION) {
|
||||
/* Action Editor (action mode) or Graph Editor (ipo mode):
|
||||
* Only use if editor is not pinned, and active object has action
|
||||
*/
|
||||
if (ac->obact && ac->obact->action) {
|
||||
SpaceAction *saction= (SpaceAction *)ac->sa->spacedata.first;
|
||||
|
||||
if (saction->pin == 0)
|
||||
return ac->obact;
|
||||
}
|
||||
}
|
||||
else if ((ac->datatype == ANIMCONT_DOPESHEET) && (ale)) {
|
||||
/* Dopesheet:
|
||||
* Only if channel is available, and is owned by an Object with an Action
|
||||
*/
|
||||
if ((ale->id) && (GS(ale->id->name) == ID_OB)) {
|
||||
Object *ob= (Object *)ale->id;
|
||||
|
||||
if (ob->action)
|
||||
return ob;
|
||||
}
|
||||
}
|
||||
// XXX todo: add F-Curves mode (Graph Editor) ...
|
||||
if (ale && ale->id)
|
||||
return BKE_animdata_from_id(ale->id);
|
||||
|
||||
/* no appropriate object found */
|
||||
return NULL;
|
||||
@@ -273,7 +254,8 @@ Object *ANIM_nla_mapping_get(bAnimContext *ac, bAnimListElem *ale)
|
||||
* (where this is called) is single-threaded anyway
|
||||
*/
|
||||
// XXX was called: map_active_strip()
|
||||
void ANIM_nla_mapping_draw(gla2DDrawInfo *di, Object *ob, short restore)
|
||||
// TODO: should this be depreceated?
|
||||
void ANIM_nla_mapping_draw(gla2DDrawInfo *di, AnimData *adt, short restore)
|
||||
{
|
||||
static rctf stored;
|
||||
|
||||
@@ -288,8 +270,8 @@ void ANIM_nla_mapping_draw(gla2DDrawInfo *di, Object *ob, short restore)
|
||||
gla2DGetMap(di, &stored);
|
||||
map= stored;
|
||||
|
||||
map.xmin= get_action_frame(ob, map.xmin);
|
||||
map.xmax= get_action_frame(ob, map.xmax);
|
||||
map.xmin= BKE_nla_tweakedit_remap(adt, map.xmin, NLATIME_CONVERT_MAP);
|
||||
map.xmax= BKE_nla_tweakedit_remap(adt, map.xmax, NLATIME_CONVERT_MAP);
|
||||
|
||||
if (map.xmin == map.xmax) map.xmax += 1.0f;
|
||||
gla2DSetMap(di, &map);
|
||||
@@ -298,36 +280,38 @@ void ANIM_nla_mapping_draw(gla2DDrawInfo *di, Object *ob, short restore)
|
||||
|
||||
/* ------------------- */
|
||||
|
||||
/* helper function for ANIM_nla_mapping_apply_ipocurve() -> "restore", i.e. mapping points back to IPO-time */
|
||||
/* helper function for ANIM_nla_mapping_apply_fcurve() -> "restore", i.e. mapping points back to action-time */
|
||||
static short bezt_nlamapping_restore(BeztEditData *bed, BezTriple *bezt)
|
||||
{
|
||||
/* object providing scaling is stored in 'data', only_keys option is stored in i1 */
|
||||
Object *ob= (Object *)bed->data;
|
||||
/* AnimData block providing scaling is stored in 'data', only_keys option is stored in i1 */
|
||||
AnimData *adt= (AnimData *)bed->data;
|
||||
short only_keys= (short)bed->i1;
|
||||
|
||||
/* adjust BezTriple handles only if allowed to */
|
||||
if (only_keys == 0) {
|
||||
bezt->vec[0][0]= get_action_frame(ob, bezt->vec[0][0]);
|
||||
bezt->vec[2][0]= get_action_frame(ob, bezt->vec[2][0]);
|
||||
}
|
||||
bezt->vec[1][0]= get_action_frame(ob, bezt->vec[1][0]);
|
||||
bezt->vec[0][0]= BKE_nla_tweakedit_remap(adt, bezt->vec[0][0], NLATIME_CONVERT_UNMAP);
|
||||
bezt->vec[2][0]= BKE_nla_tweakedit_remap(adt, bezt->vec[2][0], NLATIME_CONVERT_UNMAP);
|
||||
}
|
||||
|
||||
bezt->vec[1][0]= BKE_nla_tweakedit_remap(adt, bezt->vec[1][0], NLATIME_CONVERT_UNMAP);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* helper function for ANIM_nla_mapping_apply_ipocurve() -> "apply", i.e. mapping points to NLA-mapped global time */
|
||||
/* helper function for ANIM_nla_mapping_apply_fcurve() -> "apply", i.e. mapping points to NLA-mapped global time */
|
||||
static short bezt_nlamapping_apply(BeztEditData *bed, BezTriple *bezt)
|
||||
{
|
||||
/* object providing scaling is stored in 'data', only_keys option is stored in i1 */
|
||||
Object *ob= (Object *)bed->data;
|
||||
/* AnimData block providing scaling is stored in 'data', only_keys option is stored in i1 */
|
||||
AnimData *adt= (AnimData *)bed->data;
|
||||
short only_keys= (short)bed->i1;
|
||||
|
||||
/* adjust BezTriple handles only if allowed to */
|
||||
if (only_keys == 0) {
|
||||
bezt->vec[0][0]= get_action_frame_inv(ob, bezt->vec[0][0]);
|
||||
bezt->vec[2][0]= get_action_frame_inv(ob, bezt->vec[2][0]);
|
||||
bezt->vec[0][0]= BKE_nla_tweakedit_remap(adt, bezt->vec[0][0], NLATIME_CONVERT_MAP);
|
||||
bezt->vec[2][0]= BKE_nla_tweakedit_remap(adt, bezt->vec[2][0], NLATIME_CONVERT_MAP);
|
||||
}
|
||||
bezt->vec[1][0]= get_action_frame_inv(ob, bezt->vec[1][0]);
|
||||
|
||||
bezt->vec[1][0]= BKE_nla_tweakedit_remap(adt, bezt->vec[1][0], NLATIME_CONVERT_MAP);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -338,17 +322,17 @@ static short bezt_nlamapping_apply(BeztEditData *bed, BezTriple *bezt)
|
||||
* - restore = whether to map points back to non-mapped time
|
||||
* - only_keys = whether to only adjust the location of the center point of beztriples
|
||||
*/
|
||||
void ANIM_nla_mapping_apply_fcurve(Object *ob, FCurve *fcu, short restore, short only_keys)
|
||||
void ANIM_nla_mapping_apply_fcurve (AnimData *adt, FCurve *fcu, short restore, short only_keys)
|
||||
{
|
||||
BeztEditData bed;
|
||||
BeztEditFunc map_cb;
|
||||
|
||||
/* init edit data
|
||||
* - ob is stored in 'data'
|
||||
* - AnimData is stored in 'data'
|
||||
* - only_keys is stored in 'i1'
|
||||
*/
|
||||
memset(&bed, 0, sizeof(BeztEditData));
|
||||
bed.data= (void *)ob;
|
||||
bed.data= (void *)adt;
|
||||
bed.i1= (int)only_keys;
|
||||
|
||||
/* get editing callback */
|
||||
|
||||
@@ -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,68 @@ 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): AnimData blocks, NLA, Drivers, Keyframes.
|
||||
*
|
||||
* For this to work correctly, a standard set of data needs to be available within the scope that this
|
||||
* gets called in:
|
||||
* - ListBase anim_data;
|
||||
* - bDopeSheet *ads;
|
||||
* - bAnimListElem *ale;
|
||||
* - int items;
|
||||
*
|
||||
* - id: ID block which should have an AnimData pointer following it immediately, to use
|
||||
* - adtOk: line or block of code to execute for AnimData-blocks case (usually ANIMDATA_ADD_ANIMDATA)
|
||||
* - nlaOk: line or block of code to execute for NLA case
|
||||
* - driversOk: line or block of code to execute for Drivers case
|
||||
* - keysOk: line or block of code for Keyframes case
|
||||
*/
|
||||
#define ANIMDATA_FILTER_CASES(id, adtOk, nlaOk, driversOk, keysOk) \
|
||||
{\
|
||||
if (filter_mode & ANIMFILTER_ANIMDATA) {\
|
||||
if ((id)->adt) {\
|
||||
adtOk\
|
||||
}\
|
||||
}\
|
||||
else 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 add a pointer to an AnimData block as a channel */
|
||||
#define ANIMDATA_ADD_ANIMDATA(id) \
|
||||
{\
|
||||
ale= make_new_animlistelem((id)->adt, ANIMTYPE_ANIMDATA, NULL, ANIMTYPE_NONE, (ID *)id);\
|
||||
if (ale) {\
|
||||
BLI_addtail(anim_data, ale);\
|
||||
items++;\
|
||||
}\
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* quick macro to test if a anim-channel (F-Curve, Group, etc.) is selected in an acceptable way */
|
||||
#define ANIMCHANNEL_SELOK(test_func) \
|
||||
( !(filter_mode & (ANIMFILTER_SEL|ANIMFILTER_UNSEL)) || \
|
||||
@@ -494,6 +583,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 +630,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) {
|
||||
@@ -575,25 +682,30 @@ static int animdata_filter_action (ListBase *anim_data, bAction *act, int filter
|
||||
* cases when we should include F-Curves inside group:
|
||||
* - we don't care about visibility
|
||||
* - group is expanded
|
||||
* - we're interested in keyframes, but not if they appear in selected channels
|
||||
* - we just need the F-Curves present
|
||||
*/
|
||||
// XXX what was the selection check here for again?
|
||||
if ( (!(filter_mode & ANIMFILTER_VISIBLE) || EXPANDED_AGRP(agrp)) ||
|
||||
( /*ANIMCHANNEL_SELOK(SEL_AGRP(agrp)) &&*/ (filter_mode & ANIMFILTER_CURVESONLY) ) )
|
||||
if ( (!(filter_mode & ANIMFILTER_VISIBLE) || EXPANDED_AGRP(agrp)) || (filter_mode & ANIMFILTER_CURVESONLY) )
|
||||
{
|
||||
if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_AGRP(agrp)) {
|
||||
// XXX the 'owner' info here needs review...
|
||||
items += animdata_filter_fcurves(anim_data, agrp->channels.first, agrp, owner, ownertype, filter_mode, owner_id);
|
||||
|
||||
/* remove group from filtered list if last element is group
|
||||
* (i.e. only if group had channels, which were all hidden)
|
||||
*/
|
||||
// XXX this is really hacky... it should be fixed in a much more elegant way!
|
||||
if ( (ale) && (anim_data->last == ale) &&
|
||||
(ale->data == agrp) && (agrp->channels.first) )
|
||||
{
|
||||
BLI_freelinkN(anim_data, ale);
|
||||
items--;
|
||||
/* for the Graph Editor, curves may be set to not be visible in the view to lessen clutter,
|
||||
* but to do this, we need to check that the group doesn't have it's not-visible flag set preventing
|
||||
* all its sub-curves to be shown
|
||||
*/
|
||||
if ( !(filter_mode & ANIMFILTER_CURVEVISIBLE) || !(agrp->flag & AGRP_NOTVISIBLE) )
|
||||
{
|
||||
if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_AGRP(agrp)) {
|
||||
// XXX the 'owner' info here needs review...
|
||||
items += animdata_filter_fcurves(anim_data, agrp->channels.first, agrp, owner, ownertype, filter_mode, owner_id);
|
||||
|
||||
/* remove group from filtered list if last element is group
|
||||
* (i.e. only if group had channels, which were all hidden)
|
||||
*/
|
||||
// XXX this is really hacky... it should be fixed in a much more elegant way!
|
||||
if ( (ale) && (anim_data->last == ale) &&
|
||||
(ale->data == agrp) && (agrp->channels.first) )
|
||||
{
|
||||
BLI_freelinkN(anim_data, ale);
|
||||
items--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -610,6 +722,83 @@ static int animdata_filter_action (ListBase *anim_data, bAction *act, int filter
|
||||
return items;
|
||||
}
|
||||
|
||||
/* Include NLA-Data for NLA-Editor:
|
||||
* - when ANIMFILTER_CHANNELS is used, that means we should be filtering the list for display
|
||||
* Although the evaluation order is from the first track to the last and then apply the Action on top,
|
||||
* we present this in the UI as the Active Action followed by the last track to the first so that we
|
||||
* get the evaluation order presented as per a stack.
|
||||
* - for normal filtering (i.e. for editing), we only need the NLA-tracks but they can be in 'normal' evaluation
|
||||
* order, i.e. first to last. Otherwise, some tools may get screwed up.
|
||||
*/
|
||||
static int animdata_filter_nla (ListBase *anim_data, AnimData *adt, int filter_mode, void *owner, short ownertype, ID *owner_id)
|
||||
{
|
||||
bAnimListElem *ale;
|
||||
NlaTrack *nlt;
|
||||
NlaTrack *first=NULL, *next=NULL;
|
||||
int items = 0;
|
||||
|
||||
/* 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++;
|
||||
}
|
||||
}
|
||||
|
||||
/* first track to include will be the last one if we're filtering by channels */
|
||||
first= adt->nla_tracks.last;
|
||||
}
|
||||
else {
|
||||
/* first track to include will the the first one (as per normal) */
|
||||
first= adt->nla_tracks.first;
|
||||
}
|
||||
|
||||
/* loop over NLA Tracks - assume that the caller of this has already checked that these should be included */
|
||||
for (nlt= first; nlt; nlt= next) {
|
||||
/* 'next' NLA-Track to use depends on whether we're filtering for drawing or not */
|
||||
if (filter_mode & ANIMFILTER_CHANNELS)
|
||||
next= nlt->prev;
|
||||
else
|
||||
next= nlt->next;
|
||||
|
||||
/* if we're in NLA-tweakmode, don't show this track if it was disabled (due to tweaking) for now
|
||||
* - active track should still get shown though (even though it has disabled flag set)
|
||||
*/
|
||||
// FIXME: the channels after should still get drawn, just 'differently', and after an active-action channel
|
||||
if ((adt->flag & ADT_NLA_EDIT_ON) && (nlt->flag & NLATRACK_DISABLED) && !(nlt->flag & NLATRACK_ACTIVE))
|
||||
continue;
|
||||
|
||||
/* only work with this channel and its subchannels if it is editable */
|
||||
if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_NLT(nlt)) {
|
||||
/* only include this track if selected in a way consistent with the filtering requirements */
|
||||
if ( ANIMCHANNEL_SELOK(SEL_NLT(nlt)) ) {
|
||||
/* only include if this track is active */
|
||||
if (!(filter_mode & ANIMFILTER_ACTIVE) || (nlt->flag & NLATRACK_ACTIVE)) {
|
||||
ale= make_new_animlistelem(nlt, ANIMTYPE_NLATRACK, owner, ownertype, owner_id);
|
||||
|
||||
if (ale) {
|
||||
BLI_addtail(anim_data, ale);
|
||||
items++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* return the number of items added to the list */
|
||||
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 +941,19 @@ 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,
|
||||
{ /* AnimData blocks - do nothing... */ },
|
||||
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 +990,13 @@ 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,
|
||||
{ /* AnimData blocks - do nothing... */ },
|
||||
items += animdata_filter_nla(anim_data, ma->adt, filter_mode, ma, ANIMTYPE_DSMAT, (ID *)ma);,
|
||||
items += animdata_filter_fcurves(anim_data, ma->adt->drivers.first, NULL, ma, ANIMTYPE_DSMAT, filter_mode, (ID *)ma);,
|
||||
items += animdata_filter_action(anim_data, ma->adt->action, filter_mode, ma, ANIMTYPE_DSMAT, (ID *)ma);)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -871,15 +1057,12 @@ 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,
|
||||
{ /* AnimData blocks - do nothing... */ },
|
||||
items+= animdata_filter_nla(anim_data, iat->adt, filter_mode, iat, type, (ID *)iat);,
|
||||
items+= animdata_filter_fcurves(anim_data, adt->drivers.first, NULL, iat, type, filter_mode, (ID *)iat);,
|
||||
items += animdata_filter_action(anim_data, iat->adt->action, filter_mode, iat, type, (ID *)iat);)
|
||||
}
|
||||
|
||||
/* return the number of items added to the list */
|
||||
@@ -889,12 +1072,14 @@ 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 */
|
||||
if ((filter_mode & ANIMFILTER_CURVESONLY) == 0) {
|
||||
if ((filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) == 0) {
|
||||
/* check if filtering by selection */
|
||||
if ANIMCHANNEL_SELOK((base->flag & SELECT)) {
|
||||
ale= make_new_animlistelem(base, ANIMTYPE_OBJECT, NULL, ANIMTYPE_NONE, NULL);
|
||||
@@ -906,76 +1091,64 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B
|
||||
}
|
||||
|
||||
/* if collapsed, don't go any further (unless adding keyframes only) */
|
||||
if ( (EXPANDED_OBJC(ob) == 0) && !(filter_mode & ANIMFILTER_CURVESONLY) )
|
||||
if ( (EXPANDED_OBJC(ob) == 0) && !(filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) )
|
||||
return items;
|
||||
|
||||
/* Action 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,
|
||||
{ /* AnimData blocks - do nothing... */ },
|
||||
{ /* nla */
|
||||
/* 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? */
|
||||
if (EXPANDED_ACTC(adt->action) || !(filter_mode & ANIMFILTER_CHANNELS)) {
|
||||
// need to make the ownertype normal object here... (maybe type should be a separate one for clarity?)
|
||||
items += animdata_filter_action(anim_data, adt->action, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Drivers */
|
||||
if (ANIMDATA_HAS_DRIVERS(ob)) {
|
||||
AnimData *adt= ob->adt;
|
||||
|
||||
/* include drivers-expand widget? */
|
||||
if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
|
||||
ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLDRIVERS, base, ANIMTYPE_OBJECT, (ID *)ob);
|
||||
if (ale) {
|
||||
BLI_addtail(anim_data, ale);
|
||||
items++;
|
||||
}
|
||||
}
|
||||
|
||||
/* add F-Curve channels (drivers are F-Curves) */
|
||||
if (EXPANDED_DRVD(adt) || !(filter_mode & ANIMFILTER_CHANNELS)) {
|
||||
// need to make the ownertype normal object here... (maybe type should be a separate one for clarity?)
|
||||
items += animdata_filter_fcurves(anim_data, adt->drivers.first, NULL, ob, ANIMTYPE_OBJECT, filter_mode, (ID *)ob);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/* ShapeKeys? */
|
||||
if ((key) && !(ads->filterflag & ADS_FILTER_NOSHAPEKEYS)) {
|
||||
/* Animation or Drivers */
|
||||
if ((ads->filterflag & ADS_FILTER_ONLYDRIVERS) == 0) {
|
||||
/* include shapekey-expand widget? */
|
||||
if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
|
||||
ale= make_new_animlistelem(key, ANIMTYPE_DSSKEY, base, ANIMTYPE_OBJECT, (ID *)ob);
|
||||
if (ale) {
|
||||
BLI_addtail(anim_data, ale);
|
||||
items++;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
adt= key->adt;
|
||||
ANIMDATA_FILTER_CASES(key,
|
||||
{ /* AnimData blocks - do nothing... */ },
|
||||
{ /* nla */
|
||||
/* add NLA tracks */
|
||||
items += animdata_filter_nla(anim_data, adt, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob);
|
||||
},
|
||||
{ /* 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 +1158,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 +1192,11 @@ 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,
|
||||
{ /* AnimData blocks - do nothing... */ },
|
||||
obdata_ok= 1;,
|
||||
obdata_ok= 1;,
|
||||
obdata_ok= 1;)
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1022,14 +1205,11 @@ 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,
|
||||
{ /* AnimData blocks - do nothing... */ },
|
||||
obdata_ok= 1;,
|
||||
obdata_ok= 1;,
|
||||
obdata_ok= 1;)
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1038,18 +1218,17 @@ 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,
|
||||
{ /* AnimData blocks - do nothing... */ },
|
||||
obdata_ok= 1;,
|
||||
obdata_ok= 1;,
|
||||
obdata_ok= 1;)
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (obdata_ok)
|
||||
items += animdata_filter_dopesheet_obdata(anim_data, ads, base, filter_mode);
|
||||
|
||||
/* return the number of items added to the list */
|
||||
return items;
|
||||
@@ -1058,11 +1237,12 @@ 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;
|
||||
|
||||
/* add scene as a channel first (even if we aren't showing scenes we still need to show the scene's sub-data */
|
||||
if ((filter_mode & ANIMFILTER_CURVESONLY) == 0) {
|
||||
if ((filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) == 0) {
|
||||
/* check if filtering by selection */
|
||||
if (ANIMCHANNEL_SELOK( (sce->flag & SCE_DS_SELECTED) )) {
|
||||
ale= make_new_animlistelem(sce, ANIMTYPE_SCENE, NULL, ANIMTYPE_NONE, NULL);
|
||||
@@ -1074,77 +1254,63 @@ static int animdata_filter_dopesheet_scene (ListBase *anim_data, bDopeSheet *ads
|
||||
}
|
||||
|
||||
/* if collapsed, don't go any further (unless adding keyframes only) */
|
||||
if ( (EXPANDED_SCEC(sce) == 0) && !(filter_mode & ANIMFILTER_CURVESONLY) )
|
||||
if ( (EXPANDED_SCEC(sce) == 0) && !(filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) )
|
||||
return items;
|
||||
|
||||
/* Action 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,
|
||||
{ /* AnimData blocks - do nothing... */ },
|
||||
{ /* nla */
|
||||
/* 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? */
|
||||
if (EXPANDED_ACTC(adt->action) || !(filter_mode & ANIMFILTER_CHANNELS)) {
|
||||
items += animdata_filter_action(anim_data, adt->action, filter_mode, sce, ANIMTYPE_SCENE, (ID *)sce);
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
else {
|
||||
/* Drivers */
|
||||
if (ANIMDATA_HAS_DRIVERS(sce) && !(ads->filterflag & ADS_FILTER_NOSCE)) {
|
||||
AnimData *adt= sce->adt;
|
||||
|
||||
/* include drivers-expand widget? */
|
||||
if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
|
||||
ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLDRIVERS, sce, ANIMTYPE_SCENE, (ID *)sce);
|
||||
if (ale) {
|
||||
BLI_addtail(anim_data, ale);
|
||||
items++;
|
||||
}
|
||||
}
|
||||
|
||||
/* add F-Curve channels (drivers are F-Curves) */
|
||||
if (EXPANDED_DRVD(adt) || !(filter_mode & ANIMFILTER_CHANNELS)) {
|
||||
items += animdata_filter_fcurves(anim_data, adt->drivers.first, NULL, sce, ANIMTYPE_SCENE, filter_mode, (ID *)sce);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* world */
|
||||
if ((wo && wo->adt) && !(ads->filterflag & ADS_FILTER_NOWOR)) {
|
||||
/* Animation or Drivers */
|
||||
if ((ads->filterflag & ADS_FILTER_ONLYDRIVERS) == 0) {
|
||||
AnimData *adt= wo->adt;
|
||||
|
||||
/* include world-expand widget? */
|
||||
if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
|
||||
ale= make_new_animlistelem(wo, ANIMTYPE_DSWOR, sce, ANIMTYPE_SCENE, (ID *)sce);
|
||||
if (ale) {
|
||||
BLI_addtail(anim_data, ale);
|
||||
items++;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
/* include shapekey-expand widget? */
|
||||
/* Action, Drivers, or NLA for World */
|
||||
adt= wo->adt;
|
||||
ANIMDATA_FILTER_CASES(wo,
|
||||
{ /* AnimData blocks - do nothing... */ },
|
||||
{ /* nla */
|
||||
/* 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 +1324,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 */
|
||||
@@ -1171,6 +1352,7 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int
|
||||
{
|
||||
Scene *sce= (Scene *)ads->source;
|
||||
Base *base;
|
||||
bAnimListElem *ale;
|
||||
int items = 0;
|
||||
|
||||
/* check that we do indeed have a scene */
|
||||
@@ -1182,22 +1364,32 @@ 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,
|
||||
{
|
||||
/* for the special AnimData blocks only case, we only need to add
|
||||
* the block if it is valid... then other cases just get skipped (hence ok=0)
|
||||
*/
|
||||
ANIMDATA_ADD_ANIMDATA(sce);
|
||||
sceOk=0;
|
||||
},
|
||||
sceOk= !(ads->filterflag & ADS_FILTER_NOSCE);,
|
||||
sceOk= !(ads->filterflag & ADS_FILTER_NOSCE);,
|
||||
sceOk= !(ads->filterflag & ADS_FILTER_NOSCE);)
|
||||
if (sce->world) {
|
||||
ANIMDATA_FILTER_CASES(sce->world,
|
||||
{
|
||||
/* for the special AnimData blocks only case, we only need to add
|
||||
* the block if it is valid... then other cases just get skipped (hence ok=0)
|
||||
*/
|
||||
ANIMDATA_ADD_ANIMDATA(sce->world);
|
||||
worOk=0;
|
||||
},
|
||||
worOk= !(ads->filterflag & ADS_FILTER_NOWOR);,
|
||||
worOk= !(ads->filterflag & ADS_FILTER_NOWOR);,
|
||||
worOk= !(ads->filterflag & ADS_FILTER_NOWOR);)
|
||||
}
|
||||
|
||||
/* check if not all bad (i.e. so there is something to show) */
|
||||
@@ -1239,13 +1431,33 @@ 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,
|
||||
{
|
||||
/* for the special AnimData blocks only case, we only need to add
|
||||
* the block if it is valid... then other cases just get skipped (hence ok=0)
|
||||
*/
|
||||
ANIMDATA_ADD_ANIMDATA(ob);
|
||||
actOk=0;
|
||||
},
|
||||
actOk= 1;,
|
||||
actOk= 1;,
|
||||
actOk= 1;)
|
||||
if (key) {
|
||||
/* shapekeys */
|
||||
ANIMDATA_FILTER_CASES(key,
|
||||
{
|
||||
/* for the special AnimData blocks only case, we only need to add
|
||||
* the block if it is valid... then other cases just get skipped (hence ok=0)
|
||||
*/
|
||||
ANIMDATA_ADD_ANIMDATA(key);
|
||||
keyOk=0;
|
||||
},
|
||||
keyOk= 1;,
|
||||
keyOk= 1;,
|
||||
keyOk= 1;)
|
||||
}
|
||||
|
||||
/* materials - only for geometric types */
|
||||
@@ -1260,18 +1472,20 @@ 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,
|
||||
{
|
||||
/* for the special AnimData blocks only case, we only need to add
|
||||
* the block if it is valid... then other cases just get skipped (hence ok=0)
|
||||
*/
|
||||
ANIMDATA_ADD_ANIMDATA(ma);
|
||||
matOk=0;
|
||||
},
|
||||
matOk= 1;,
|
||||
matOk= 1;,
|
||||
matOk= 1;)
|
||||
|
||||
if (matOk)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1280,19 +1494,52 @@ 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,
|
||||
if ((ads->filterflag & ADS_FILTER_NOCAM)==0) {
|
||||
/* for the special AnimData blocks only case, we only need to add
|
||||
* the block if it is valid... then other cases just get skipped (hence ok=0)
|
||||
*/
|
||||
ANIMDATA_ADD_ANIMDATA(ca);
|
||||
dataOk=0;
|
||||
},
|
||||
dataOk= !(ads->filterflag & ADS_FILTER_NOCAM);,
|
||||
dataOk= !(ads->filterflag & ADS_FILTER_NOCAM);,
|
||||
dataOk= !(ads->filterflag & ADS_FILTER_NOCAM);)
|
||||
}
|
||||
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,
|
||||
if ((ads->filterflag & ADS_FILTER_NOLAM)==0) {
|
||||
/* for the special AnimData blocks only case, we only need to add
|
||||
* the block if it is valid... then other cases just get skipped (hence ok=0)
|
||||
*/
|
||||
ANIMDATA_ADD_ANIMDATA(la);
|
||||
dataOk=0;
|
||||
},
|
||||
dataOk= !(ads->filterflag & ADS_FILTER_NOLAM);,
|
||||
dataOk= !(ads->filterflag & ADS_FILTER_NOLAM);,
|
||||
dataOk= !(ads->filterflag & ADS_FILTER_NOLAM);)
|
||||
}
|
||||
break;
|
||||
case OB_CURVE: /* ------- Curve ---------- */
|
||||
{
|
||||
Curve *cu= (Curve *)ob->data;
|
||||
dataOk= 0;
|
||||
ANIMDATA_FILTER_CASES(cu,
|
||||
if ((ads->filterflag & ADS_FILTER_NOCUR)==0) {
|
||||
/* for the special AnimData blocks only case, we only need to add
|
||||
* the block if it is valid... then other cases just get skipped (hence ok=0)
|
||||
*/
|
||||
ANIMDATA_ADD_ANIMDATA(cu);
|
||||
dataOk=0;
|
||||
},
|
||||
dataOk= !(ads->filterflag & ADS_FILTER_NOCUR);,
|
||||
dataOk= !(ads->filterflag & ADS_FILTER_NOCUR);,
|
||||
dataOk= !(ads->filterflag & ADS_FILTER_NOCUR);)
|
||||
}
|
||||
break;
|
||||
default: /* --- other --- */
|
||||
@@ -1400,6 +1647,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;
|
||||
}
|
||||
|
||||
@@ -83,10 +83,12 @@ static void change_frame_apply(bContext *C, wmOperator *op)
|
||||
Scene *scene= CTX_data_scene(C);
|
||||
int cfra;
|
||||
|
||||
/* get frame, and clamp to MINFRAME */
|
||||
/* get frame, and clamp to MINAFRAME
|
||||
* - not MINFRAME, since it's useful to be able to key a few-frames back
|
||||
*/
|
||||
cfra= RNA_int_get(op->ptr, "frame");
|
||||
|
||||
if (cfra < MINFRAME) cfra= MINFRAME;
|
||||
if (cfra < MINAFRAME) cfra= MINAFRAME;
|
||||
CFRA= cfra;
|
||||
|
||||
WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
|
||||
@@ -209,7 +211,7 @@ void ANIM_OT_change_frame(wmOperatorType *ot)
|
||||
ot->modal= change_frame_modal;
|
||||
|
||||
/* rna */
|
||||
RNA_def_int(ot->srna, "frame", 0, 1, MAXFRAME, "Frame", "", 1, MAXFRAME);
|
||||
RNA_def_int(ot->srna, "frame", 0, MINAFRAME, MAXFRAME, "Frame", "", MINAFRAME, MAXFRAME);
|
||||
}
|
||||
|
||||
/* ****************** set preview range operator ****************************/
|
||||
|
||||
@@ -1,5 +1,30 @@
|
||||
/* Testing code for 2.5 animation system
|
||||
* Copyright 2009, Joshua Leung
|
||||
/**
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): Joshua Leung (full recode)
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -94,7 +119,7 @@ FCurve *verify_driver_fcurve (ID *id, const char rna_path[], const int array_ind
|
||||
fcu->driver= MEM_callocN(sizeof(ChannelDriver), "ChannelDriver");
|
||||
|
||||
/* add simple generator modifier for driver so that there is some visible representation */
|
||||
fcurve_add_modifier(fcu, FMODIFIER_TYPE_GENERATOR);
|
||||
add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR);
|
||||
|
||||
/* just add F-Curve to end of driver list */
|
||||
BLI_addtail(&adt->drivers, fcu);
|
||||
|
||||
679
source/blender/editors/animation/fmodifier_ui.c
Normal file
679
source/blender/editors/animation/fmodifier_ui.c
Normal file
@@ -0,0 +1,679 @@
|
||||
/**
|
||||
* $Id:
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2009 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
*
|
||||
* Contributor(s): Blender Foundation, Joshua Leung
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/* User-Interface Stuff for F-Modifiers:
|
||||
* This file defines the (C-Coded) templates + editing callbacks needed
|
||||
* by the interface stuff or F-Modifiers, as used by F-Curves in the Graph Editor,
|
||||
* and NLA-Strips in the NLA Editor.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
|
||||
#include "DNA_anim_types.h"
|
||||
#include "DNA_action_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_screen_types.h"
|
||||
#include "DNA_userdef_types.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_arithb.h"
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_editVert.h"
|
||||
#include "BLI_rand.h"
|
||||
|
||||
#include "BKE_animsys.h"
|
||||
#include "BKE_action.h"
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_curve.h"
|
||||
#include "BKE_customdata.h"
|
||||
#include "BKE_depsgraph.h"
|
||||
#include "BKE_fcurve.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_nla.h"
|
||||
#include "BKE_scene.h"
|
||||
#include "BKE_screen.h"
|
||||
#include "BKE_utildefines.h"
|
||||
|
||||
#include "BIF_gl.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_define.h"
|
||||
|
||||
#include "ED_anim_api.h"
|
||||
#include "ED_keyframing.h"
|
||||
#include "ED_screen.h"
|
||||
#include "ED_types.h"
|
||||
#include "ED_util.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
#include "UI_resources.h"
|
||||
#include "UI_view2d.h"
|
||||
|
||||
// XXX! --------------------------------
|
||||
/* temporary definition for limits of float number buttons (FLT_MAX tends to infinity with old system) */
|
||||
#define UI_FLT_MAX 10000.0f
|
||||
|
||||
/* ********************************************** */
|
||||
|
||||
#define B_REDR 1
|
||||
#define B_FMODIFIER_REDRAW 20
|
||||
|
||||
/* macro for use here to draw background box and set height */
|
||||
// XXX for now, roundbox has it's callback func set to NULL to not intercept events
|
||||
#define DRAW_BACKDROP(height) \
|
||||
{ \
|
||||
uiDefBut(block, ROUNDBOX, B_REDR, "", -3, yco-height, width+3, height-1, NULL, 5.0, 0.0, 12.0, (float)rb_col, ""); \
|
||||
}
|
||||
|
||||
/* callback to verify modifier data */
|
||||
static void validate_fmodifier_cb (bContext *C, void *fcm_v, void *dummy)
|
||||
{
|
||||
FModifier *fcm= (FModifier *)fcm_v;
|
||||
FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
|
||||
|
||||
/* call the verify callback on the modifier if applicable */
|
||||
if (fmi && fmi->verify_data)
|
||||
fmi->verify_data(fcm);
|
||||
}
|
||||
|
||||
/* callback to set the active modifier */
|
||||
static void activate_fmodifier_cb (bContext *C, void *fmods_v, void *fcm_v)
|
||||
{
|
||||
ListBase *modifiers = (ListBase *)fmods_v;
|
||||
FModifier *fcm= (FModifier *)fcm_v;
|
||||
|
||||
/* call API function to set the active modifier for active modifier-stack */
|
||||
set_active_fmodifier(modifiers, fcm);
|
||||
}
|
||||
|
||||
/* callback to remove the given modifier */
|
||||
static void delete_fmodifier_cb (bContext *C, void *fmods_v, void *fcm_v)
|
||||
{
|
||||
ListBase *modifiers = (ListBase *)fmods_v;
|
||||
FModifier *fcm= (FModifier *)fcm_v;
|
||||
|
||||
/* remove the given F-Modifier from the active modifier-stack */
|
||||
remove_fmodifier(modifiers, fcm);
|
||||
}
|
||||
|
||||
/* --------------- */
|
||||
|
||||
/* draw settings for generator modifier */
|
||||
static void draw_modifier__generator(uiLayout *layout, ID *id, FModifier *fcm, short width)
|
||||
{
|
||||
FMod_Generator *data= (FMod_Generator *)fcm->data;
|
||||
uiLayout *col, *row;
|
||||
uiBlock *block;
|
||||
uiBut *but;
|
||||
PointerRNA ptr;
|
||||
|
||||
/* init the RNA-pointer */
|
||||
RNA_pointer_create(id, &RNA_FModifierFunctionGenerator, fcm, &ptr);
|
||||
|
||||
/* basic settings (backdrop + mode selector + some padding) */
|
||||
col= uiLayoutColumn(layout, 1);
|
||||
block= uiLayoutGetBlock(layout);
|
||||
uiBlockBeginAlign(block);
|
||||
but= uiDefButR(block, MENU, B_FMODIFIER_REDRAW, NULL, 0, 0, width-30, UI_UNIT_Y, &ptr, "mode", -1, 0, 0, -1, -1, NULL);
|
||||
uiButSetFunc(but, validate_fmodifier_cb, fcm, NULL);
|
||||
|
||||
uiDefButR(block, TOG, B_FMODIFIER_REDRAW, NULL, 0, 0, width-30, UI_UNIT_Y, &ptr, "additive", -1, 0, 0, -1, -1, NULL);
|
||||
uiBlockEndAlign(block);
|
||||
|
||||
/* now add settings for individual modes */
|
||||
switch (data->mode) {
|
||||
case FCM_GENERATOR_POLYNOMIAL: /* polynomial expression */
|
||||
{
|
||||
float *cp = NULL;
|
||||
char xval[32];
|
||||
unsigned int i;
|
||||
|
||||
/* draw polynomial order selector */
|
||||
row= uiLayoutRow(layout, 0);
|
||||
block= uiLayoutGetBlock(row);
|
||||
but= uiDefButI(block, NUM, B_FMODIFIER_REDRAW, "Poly Order: ", 10,0,width-30,19, &data->poly_order, 1, 100, 0, 0, "'Order' of the Polynomial - for a polynomial with n terms, 'order' is n-1");
|
||||
uiButSetFunc(but, validate_fmodifier_cb, fcm, NULL);
|
||||
|
||||
|
||||
/* draw controls for each coefficient and a + sign at end of row */
|
||||
row= uiLayoutRow(layout, 1);
|
||||
block= uiLayoutGetBlock(row);
|
||||
uiDefBut(block, LABEL, 1, "y = ", 0, 0, 50, 20, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
cp= data->coefficients;
|
||||
for (i=0; (i < data->arraysize) && (cp); i++, cp++) {
|
||||
/* coefficient */
|
||||
uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 0, 0, 150, 20, cp, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "Coefficient for polynomial");
|
||||
|
||||
/* 'x' param (and '+' if necessary) */
|
||||
if (i) {
|
||||
if (i == 1)
|
||||
strcpy(xval, "x");
|
||||
else
|
||||
sprintf(xval, "x^%d", i);
|
||||
uiDefBut(block, LABEL, 1, xval, 0, 0, 50, 20, NULL, 0.0, 0.0, 0, 0, "Power of x");
|
||||
}
|
||||
|
||||
if ( (i != (data->arraysize - 1)) || ((i==0) && data->arraysize==2) ) {
|
||||
uiDefBut(block, LABEL, 1, "+", 0,0 , 30, 20, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
/* next coefficient on a new row */
|
||||
row= uiLayoutRow(layout, 1);
|
||||
block= uiLayoutGetBlock(row);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* factorised polynomial expression */
|
||||
{
|
||||
float *cp = NULL;
|
||||
unsigned int i;
|
||||
|
||||
/* draw polynomial order selector */
|
||||
row= uiLayoutRow(layout, 0);
|
||||
block= uiLayoutGetBlock(row);
|
||||
but= uiDefButI(block, NUM, B_FMODIFIER_REDRAW, "Poly Order: ", 0,0,width-30,19, &data->poly_order, 1, 100, 0, 0, "'Order' of the Polynomial - for a polynomial with n terms, 'order' is n-1");
|
||||
uiButSetFunc(but, validate_fmodifier_cb, fcm, NULL);
|
||||
|
||||
|
||||
/* draw controls for each pair of coefficients */
|
||||
row= uiLayoutRow(layout, 1);
|
||||
block= uiLayoutGetBlock(row);
|
||||
uiDefBut(block, LABEL, 1, "y=", 0, 0, 50, 20, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
cp= data->coefficients;
|
||||
for (i=0; (i < data->poly_order) && (cp); i++, cp+=2) {
|
||||
/* opening bracket */
|
||||
uiDefBut(block, LABEL, 1, "(", 0, 0, 20, 20, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
/* coefficients */
|
||||
uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 0, 0, 100, 20, cp, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "Coefficient of x");
|
||||
|
||||
uiDefBut(block, LABEL, 1, "x+", 0, 0, 40, 20, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 0, 0, 100, 20, cp+1, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "Second coefficient");
|
||||
|
||||
/* closing bracket and '+' sign */
|
||||
if ( (i != (data->poly_order - 1)) || ((i==0) && data->poly_order==2) ) {
|
||||
uiDefBut(block, LABEL, 1, ") +", 0, 0, 30, 20, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
/* set up new row for the next pair of coefficients*/
|
||||
row= uiLayoutRow(layout, 1);
|
||||
block= uiLayoutGetBlock(row);
|
||||
}
|
||||
else
|
||||
uiDefBut(block, LABEL, 1, ")", 0, 0, 20, 20, NULL, 0.0, 0.0, 0, 0, "");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------- */
|
||||
|
||||
/* draw settings for noise modifier */
|
||||
static void draw_modifier__fn_generator(uiLayout *layout, ID *id, FModifier *fcm, short width)
|
||||
{
|
||||
uiLayout *col;
|
||||
PointerRNA ptr;
|
||||
|
||||
/* init the RNA-pointer */
|
||||
RNA_pointer_create(id, &RNA_FModifierFunctionGenerator, fcm, &ptr);
|
||||
|
||||
/* add the settings */
|
||||
col= uiLayoutColumn(layout, 1);
|
||||
uiItemR(col, "", 0, &ptr, "type", 0, 0, 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "additive", 0, 0, 1);
|
||||
|
||||
col= uiLayoutColumn(layout, 0); // no grouping for now
|
||||
uiItemR(col, NULL, 0, &ptr, "amplitude", 0, 0, 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "phase_multiplier", 0, 0, 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "phase_offset", 0, 0, 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "value_offset", 0, 0, 0);
|
||||
}
|
||||
|
||||
/* --------------- */
|
||||
|
||||
/* draw settings for cycles modifier */
|
||||
static void draw_modifier__cycles(uiLayout *layout, ID *id, FModifier *fcm, short width)
|
||||
{
|
||||
uiLayout *split, *col;
|
||||
PointerRNA ptr;
|
||||
|
||||
/* init the RNA-pointer */
|
||||
RNA_pointer_create(id, &RNA_FModifierCycles, fcm, &ptr);
|
||||
|
||||
/* split into 2 columns
|
||||
* NOTE: the mode comboboxes shouldn't get labels, otherwise there isn't enough room
|
||||
*/
|
||||
split= uiLayoutSplit(layout, 0.5f);
|
||||
|
||||
/* before range */
|
||||
col= uiLayoutColumn(split, 1);
|
||||
uiItemL(col, "Before:", 0);
|
||||
uiItemR(col, "", 0, &ptr, "before_mode", 0, 0, 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "before_cycles", 0, 0, 0);
|
||||
|
||||
/* after range */
|
||||
col= uiLayoutColumn(split, 1);
|
||||
uiItemL(col, "After:", 0);
|
||||
uiItemR(col, "", 0, &ptr, "after_mode", 0, 0, 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "after_cycles", 0, 0, 0);
|
||||
}
|
||||
|
||||
/* --------------- */
|
||||
|
||||
/* draw settings for noise modifier */
|
||||
static void draw_modifier__noise(uiLayout *layout, ID *id, FModifier *fcm, short width)
|
||||
{
|
||||
uiLayout *split, *col;
|
||||
PointerRNA ptr;
|
||||
|
||||
/* init the RNA-pointer */
|
||||
RNA_pointer_create(id, &RNA_FModifierNoise, fcm, &ptr);
|
||||
|
||||
/* blending mode */
|
||||
uiItemR(layout, NULL, 0, &ptr, "modification", 0, 0, 0);
|
||||
|
||||
/* split into 2 columns */
|
||||
split= uiLayoutSplit(layout, 0.5f);
|
||||
|
||||
/* col 1 */
|
||||
col= uiLayoutColumn(split, 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "size", 0, 0, 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "strength", 0, 0, 0);
|
||||
|
||||
/* col 2 */
|
||||
col= uiLayoutColumn(split, 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "phase", 0, 0, 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "depth", 0, 0, 0);
|
||||
}
|
||||
|
||||
/* --------------- */
|
||||
|
||||
#define BINARYSEARCH_FRAMEEQ_THRESH 0.0001
|
||||
|
||||
/* Binary search algorithm for finding where to insert Envelope Data Point.
|
||||
* Returns the index to insert at (data already at that index will be offset if replace is 0)
|
||||
*/
|
||||
static int binarysearch_fcm_envelopedata_index (FCM_EnvelopeData array[], float frame, int arraylen, short *exists)
|
||||
{
|
||||
int start=0, end=arraylen;
|
||||
int loopbreaker= 0, maxloop= arraylen * 2;
|
||||
|
||||
/* initialise exists-flag first */
|
||||
*exists= 0;
|
||||
|
||||
/* sneaky optimisations (don't go through searching process if...):
|
||||
* - keyframe to be added is to be added out of current bounds
|
||||
* - keyframe to be added would replace one of the existing ones on bounds
|
||||
*/
|
||||
if ((arraylen <= 0) || (array == NULL)) {
|
||||
printf("Warning: binarysearch_fcm_envelopedata_index() encountered invalid array \n");
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
/* check whether to add before/after/on */
|
||||
float framenum;
|
||||
|
||||
/* 'First' Point (when only one point, this case is used) */
|
||||
framenum= array[0].time;
|
||||
if (IS_EQT(frame, framenum, BINARYSEARCH_FRAMEEQ_THRESH)) {
|
||||
*exists = 1;
|
||||
return 0;
|
||||
}
|
||||
else if (frame < framenum)
|
||||
return 0;
|
||||
|
||||
/* 'Last' Point */
|
||||
framenum= array[(arraylen-1)].time;
|
||||
if (IS_EQT(frame, framenum, BINARYSEARCH_FRAMEEQ_THRESH)) {
|
||||
*exists= 1;
|
||||
return (arraylen - 1);
|
||||
}
|
||||
else if (frame > framenum)
|
||||
return arraylen;
|
||||
}
|
||||
|
||||
|
||||
/* most of the time, this loop is just to find where to put it
|
||||
* - 'loopbreaker' is just here to prevent infinite loops
|
||||
*/
|
||||
for (loopbreaker=0; (start <= end) && (loopbreaker < maxloop); loopbreaker++) {
|
||||
/* compute and get midpoint */
|
||||
int mid = start + ((end - start) / 2); /* we calculate the midpoint this way to avoid int overflows... */
|
||||
float midfra= array[mid].time;
|
||||
|
||||
/* check if exactly equal to midpoint */
|
||||
if (IS_EQT(frame, midfra, BINARYSEARCH_FRAMEEQ_THRESH)) {
|
||||
*exists = 1;
|
||||
return mid;
|
||||
}
|
||||
|
||||
/* repeat in upper/lower half */
|
||||
if (frame > midfra)
|
||||
start= mid + 1;
|
||||
else if (frame < midfra)
|
||||
end= mid - 1;
|
||||
}
|
||||
|
||||
/* print error if loop-limit exceeded */
|
||||
if (loopbreaker == (maxloop-1)) {
|
||||
printf("Error: binarysearch_fcm_envelopedata_index() was taking too long \n");
|
||||
|
||||
// include debug info
|
||||
printf("\tround = %d: start = %d, end = %d, arraylen = %d \n", loopbreaker, start, end, arraylen);
|
||||
}
|
||||
|
||||
/* not found, so return where to place it */
|
||||
return start;
|
||||
}
|
||||
|
||||
/* callback to add new envelope data point */
|
||||
// TODO: should we have a separate file for things like this?
|
||||
static void fmod_envelope_addpoint_cb (bContext *C, void *fcm_dv, void *dummy)
|
||||
{
|
||||
Scene *scene= CTX_data_scene(C);
|
||||
FMod_Envelope *env= (FMod_Envelope *)fcm_dv;
|
||||
FCM_EnvelopeData *fedn;
|
||||
FCM_EnvelopeData fed;
|
||||
|
||||
/* init template data */
|
||||
fed.min= -1.0f;
|
||||
fed.max= 1.0f;
|
||||
fed.time= (float)scene->r.cfra; // XXX make this int for ease of use?
|
||||
fed.f1= fed.f2= 0;
|
||||
|
||||
/* check that no data exists for the current frame... */
|
||||
if (env->data) {
|
||||
short exists = -1;
|
||||
int i= binarysearch_fcm_envelopedata_index(env->data, (float)(scene->r.cfra), env->totvert, &exists);
|
||||
|
||||
/* binarysearch_...() will set exists by default to 0, so if it is non-zero, that means that the point exists already */
|
||||
if (exists)
|
||||
return;
|
||||
|
||||
/* add new */
|
||||
fedn= MEM_callocN((env->totvert+1)*sizeof(FCM_EnvelopeData), "FCM_EnvelopeData");
|
||||
|
||||
/* add the points that should occur before the point to be pasted */
|
||||
if (i > 0)
|
||||
memcpy(fedn, env->data, i*sizeof(FCM_EnvelopeData));
|
||||
|
||||
/* add point to paste at index i */
|
||||
*(fedn + i)= fed;
|
||||
|
||||
/* add the points that occur after the point to be pasted */
|
||||
if (i < env->totvert)
|
||||
memcpy(fedn+i+1, env->data+i, (env->totvert-i)*sizeof(FCM_EnvelopeData));
|
||||
|
||||
/* replace (+ free) old with new */
|
||||
MEM_freeN(env->data);
|
||||
env->data= fedn;
|
||||
|
||||
env->totvert++;
|
||||
}
|
||||
else {
|
||||
env->data= MEM_callocN(sizeof(FCM_EnvelopeData), "FCM_EnvelopeData");
|
||||
*(env->data)= fed;
|
||||
|
||||
env->totvert= 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* callback to remove envelope data point */
|
||||
// TODO: should we have a separate file for things like this?
|
||||
static void fmod_envelope_deletepoint_cb (bContext *C, void *fcm_dv, void *ind_v)
|
||||
{
|
||||
FMod_Envelope *env= (FMod_Envelope *)fcm_dv;
|
||||
FCM_EnvelopeData *fedn;
|
||||
int index= GET_INT_FROM_POINTER(ind_v);
|
||||
|
||||
/* check that no data exists for the current frame... */
|
||||
if (env->totvert > 1) {
|
||||
/* allocate a new smaller array */
|
||||
fedn= MEM_callocN(sizeof(FCM_EnvelopeData)*(env->totvert-1), "FCM_EnvelopeData");
|
||||
|
||||
memcpy(fedn, &env->data, sizeof(FCM_EnvelopeData)*(index));
|
||||
memcpy(&fedn[index], &env->data[index+1], sizeof(FCM_EnvelopeData)*(env->totvert-index-1));
|
||||
|
||||
/* free old array, and set the new */
|
||||
MEM_freeN(env->data);
|
||||
env->data= fedn;
|
||||
env->totvert--;
|
||||
}
|
||||
else {
|
||||
/* just free array, since the only vert was deleted */
|
||||
if (env->data)
|
||||
MEM_freeN(env->data);
|
||||
env->totvert= 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* draw settings for envelope modifier */
|
||||
static void draw_modifier__envelope(uiLayout *layout, ID *id, FModifier *fcm, short width)
|
||||
{
|
||||
FMod_Envelope *env= (FMod_Envelope *)fcm->data;
|
||||
FCM_EnvelopeData *fed;
|
||||
uiLayout *col, *row;
|
||||
uiBlock *block;
|
||||
uiBut *but;
|
||||
PointerRNA ptr;
|
||||
int i;
|
||||
|
||||
/* init the RNA-pointer */
|
||||
RNA_pointer_create(id, &RNA_FModifierEnvelope, fcm, &ptr);
|
||||
|
||||
/* general settings */
|
||||
col= uiLayoutColumn(layout, 1);
|
||||
uiItemL(col, "Envelope:", 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "reference_value", 0, 0, 0);
|
||||
|
||||
row= uiLayoutRow(col, 1);
|
||||
uiItemR(row, "Min", 0, &ptr, "default_minimum", 0, 0, 0);
|
||||
uiItemR(row, "Max", 0, &ptr, "default_maximum", 0, 0, 0);
|
||||
|
||||
/* control points header */
|
||||
// TODO: move this control-point control stuff to using the new special widgets for lists
|
||||
// the current way is far too cramped
|
||||
row= uiLayoutRow(layout, 0);
|
||||
block= uiLayoutGetBlock(row);
|
||||
|
||||
uiDefBut(block, LABEL, 1, "Control Points:", 0, 0, 150, 20, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
but= uiDefBut(block, BUT, B_FMODIFIER_REDRAW, "Add Point", 0,0,150,19, NULL, 0, 0, 0, 0, "Adds a new control-point to the envelope on the current frame");
|
||||
uiButSetFunc(but, fmod_envelope_addpoint_cb, env, NULL);
|
||||
|
||||
/* control points list */
|
||||
for (i=0, fed=env->data; i < env->totvert; i++, fed++) {
|
||||
/* get a new row to operate on */
|
||||
row= uiLayoutRow(layout, 1);
|
||||
block= uiLayoutGetBlock(row);
|
||||
|
||||
uiBlockBeginAlign(block);
|
||||
but=uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Fra:", 0, 0, 90, 20, &fed->time, -UI_FLT_MAX, UI_FLT_MAX, 10, 1, "Frame that envelope point occurs");
|
||||
uiButSetFunc(but, validate_fmodifier_cb, fcm, NULL);
|
||||
|
||||
uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Min:", 0, 0, 100, 20, &fed->min, -UI_FLT_MAX, UI_FLT_MAX, 10, 2, "Minimum bound of envelope at this point");
|
||||
uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Max:", 0, 0, 100, 20, &fed->max, -UI_FLT_MAX, UI_FLT_MAX, 10, 2, "Maximum bound of envelope at this point");
|
||||
|
||||
but= uiDefIconBut(block, BUT, B_FMODIFIER_REDRAW, ICON_X, 0, 0, 18, 20, NULL, 0.0, 0.0, 0.0, 0.0, "Delete envelope control point");
|
||||
uiButSetFunc(but, fmod_envelope_deletepoint_cb, env, SET_INT_IN_POINTER(i));
|
||||
uiBlockBeginAlign(block);
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------- */
|
||||
|
||||
/* draw settings for limits modifier */
|
||||
static void draw_modifier__limits(uiLayout *layout, ID *id, FModifier *fcm, short width)
|
||||
{
|
||||
uiLayout *split, *col, *row;
|
||||
PointerRNA ptr;
|
||||
|
||||
/* init the RNA-pointer */
|
||||
RNA_pointer_create(id, &RNA_FModifierLimits, fcm, &ptr);
|
||||
|
||||
/* row 1: minimum */
|
||||
{
|
||||
row= uiLayoutRow(layout, 0);
|
||||
|
||||
/* split into 2 columns */
|
||||
split= uiLayoutSplit(layout, 0.5f);
|
||||
|
||||
/* x-minimum */
|
||||
col= uiLayoutColumn(split, 1);
|
||||
uiItemR(col, NULL, 0, &ptr, "use_minimum_x", 0, 0, 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "minimum_x", 0, 0, 0);
|
||||
|
||||
/* y-minimum*/
|
||||
col= uiLayoutColumn(split, 1);
|
||||
uiItemR(col, NULL, 0, &ptr, "use_minimum_y", 0, 0, 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "minimum_y", 0, 0, 0);
|
||||
}
|
||||
|
||||
/* row 2: minimum */
|
||||
{
|
||||
row= uiLayoutRow(layout, 0);
|
||||
|
||||
/* split into 2 columns */
|
||||
split= uiLayoutSplit(layout, 0.5f);
|
||||
|
||||
/* x-minimum */
|
||||
col= uiLayoutColumn(split, 1);
|
||||
uiItemR(col, NULL, 0, &ptr, "use_maximum_x", 0, 0, 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "maximum_x", 0, 0, 0);
|
||||
|
||||
/* y-minimum*/
|
||||
col= uiLayoutColumn(split, 1);
|
||||
uiItemR(col, NULL, 0, &ptr, "use_maximum_y", 0, 0, 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "maximum_y", 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------- */
|
||||
|
||||
|
||||
void ANIM_uiTemplate_fmodifier_draw (uiLayout *layout, ID *id, ListBase *modifiers, FModifier *fcm)
|
||||
{
|
||||
FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
|
||||
uiLayout *box, *row, *subrow;
|
||||
uiBlock *block;
|
||||
uiBut *but;
|
||||
short width= 314;
|
||||
|
||||
/* draw header */
|
||||
{
|
||||
/* get layout-row + UI-block for this */
|
||||
box= uiLayoutBox(layout);
|
||||
|
||||
row= uiLayoutRow(box, 0);
|
||||
block= uiLayoutGetBlock(row); // err...
|
||||
|
||||
uiBlockSetEmboss(block, UI_EMBOSSN);
|
||||
|
||||
/* left-align -------------------------------------------- */
|
||||
subrow= uiLayoutRow(row, 0);
|
||||
uiLayoutSetAlignment(subrow, UI_LAYOUT_ALIGN_LEFT);
|
||||
|
||||
/* expand */
|
||||
uiDefIconButBitS(block, ICONTOG, FMODIFIER_FLAG_EXPANDED, B_REDR, ICON_TRIA_RIGHT, 0, -1, UI_UNIT_X, UI_UNIT_Y, &fcm->flag, 0.0, 0.0, 0, 0, "Modifier is expanded.");
|
||||
|
||||
/* checkbox for 'active' status (for now) */
|
||||
but= uiDefIconButBitS(block, ICONTOG, FMODIFIER_FLAG_ACTIVE, B_REDR, ICON_RADIOBUT_OFF, 0, -1, UI_UNIT_X, UI_UNIT_Y, &fcm->flag, 0.0, 0.0, 0, 0, "Modifier is active one.");
|
||||
uiButSetFunc(but, activate_fmodifier_cb, modifiers, fcm);
|
||||
|
||||
/* name */
|
||||
if (fmi)
|
||||
uiDefBut(block, LABEL, 1, fmi->name, 0, 0, 150, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "F-Curve Modifier Type. Click to make modifier active one.");
|
||||
else
|
||||
uiDefBut(block, LABEL, 1, "<Unknown Modifier>", 0, 0, 150, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "F-Curve Modifier Type. Click to make modifier active one.");
|
||||
|
||||
/* right-align ------------------------------------------- */
|
||||
subrow= uiLayoutRow(row, 0);
|
||||
uiLayoutSetAlignment(subrow, UI_LAYOUT_ALIGN_RIGHT);
|
||||
|
||||
/* 'mute' button */
|
||||
uiDefIconButBitS(block, ICONTOG, FMODIFIER_FLAG_MUTED, B_REDR, ICON_MUTE_IPO_OFF, 0, 0, UI_UNIT_X, UI_UNIT_Y, &fcm->flag, 0.0, 0.0, 0, 0, "Modifier is temporarily muted (not evaluated).");
|
||||
|
||||
/* delete button */
|
||||
but= uiDefIconBut(block, BUT, B_REDR, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, "Delete F-Curve Modifier.");
|
||||
uiButSetFunc(but, delete_fmodifier_cb, modifiers, fcm);
|
||||
|
||||
uiBlockSetEmboss(block, UI_EMBOSS);
|
||||
}
|
||||
|
||||
/* when modifier is expanded, draw settings */
|
||||
if (fcm->flag & FMODIFIER_FLAG_EXPANDED) {
|
||||
/* set up the flexible-box layout which acts as the backdrop for the modifier settings */
|
||||
box= uiLayoutBox(layout);
|
||||
|
||||
/* draw settings for individual modifiers */
|
||||
switch (fcm->type) {
|
||||
case FMODIFIER_TYPE_GENERATOR: /* Generator */
|
||||
draw_modifier__generator(box, id, fcm, width);
|
||||
break;
|
||||
|
||||
case FMODIFIER_TYPE_FN_GENERATOR: /* Built-In Function Generator */
|
||||
draw_modifier__fn_generator(box, id, fcm, width);
|
||||
break;
|
||||
|
||||
case FMODIFIER_TYPE_CYCLES: /* Cycles */
|
||||
draw_modifier__cycles(box, id, fcm, width);
|
||||
break;
|
||||
|
||||
case FMODIFIER_TYPE_ENVELOPE: /* Envelope */
|
||||
draw_modifier__envelope(box, id, fcm, width);
|
||||
break;
|
||||
|
||||
case FMODIFIER_TYPE_LIMITS: /* Limits */
|
||||
draw_modifier__limits(box, id, fcm, width);
|
||||
break;
|
||||
|
||||
case FMODIFIER_TYPE_NOISE: /* Noise */
|
||||
draw_modifier__noise(box, id, fcm, width);
|
||||
break;
|
||||
|
||||
default: /* unknown type */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ********************************************** */
|
||||
@@ -51,7 +51,6 @@
|
||||
#include "DNA_armature_types.h"
|
||||
#include "DNA_camera_types.h"
|
||||
#include "DNA_curve_types.h"
|
||||
#include "DNA_ipo_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_screen_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
@@ -64,6 +63,7 @@
|
||||
#include "DNA_gpencil_types.h"
|
||||
#include "DNA_windowmanager_types.h"
|
||||
#include "DNA_world_types.h"
|
||||
#include "DNA_view2d_types.h"
|
||||
|
||||
#include "BKE_action.h"
|
||||
#include "BKE_depsgraph.h"
|
||||
@@ -234,45 +234,87 @@ static ActKeyColumn *cfra_find_actkeycolumn (ListBase *keys, float cframe)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if 0 // disabled, as some intel cards have problems with this
|
||||
/* Draw a simple diamond shape with a filled in center (in screen space) */
|
||||
static void draw_key_but(int x, int y, short w, short h, int sel)
|
||||
{
|
||||
int xmin= x, ymin= y;
|
||||
int xmax= x+w-1, ymax= y+h-1;
|
||||
int xc= (xmin+xmax)/2, yc= (ymin+ymax)/2;
|
||||
|
||||
/* interior - hardcoded colors (for selected and unselected only) */
|
||||
if (sel) glColor3ub(0xF1, 0xCA, 0x13);
|
||||
else glColor3ub(0xE9, 0xE9, 0xE9);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glVertex2i(xc, ymin);
|
||||
glVertex2i(xmax, yc);
|
||||
glVertex2i(xc, ymax);
|
||||
glVertex2i(xmin, yc);
|
||||
glEnd();
|
||||
|
||||
|
||||
/* outline */
|
||||
glColor3ub(0, 0, 0);
|
||||
|
||||
glBegin(GL_LINE_LOOP);
|
||||
glVertex2i(xc, ymin);
|
||||
glVertex2i(xmax, yc);
|
||||
glVertex2i(xc, ymax);
|
||||
glVertex2i(xmin, yc);
|
||||
glEnd();
|
||||
}
|
||||
#endif
|
||||
/* coordinates for diamond shape */
|
||||
static const float _unit_diamond_shape[4][2] = {
|
||||
{0.0f, 1.0f}, /* top vert */
|
||||
{1.0f, 0.0f}, /* mid-right */
|
||||
{0.0f, -1.0f}, /* bottom vert */
|
||||
{-1.0f, 0.0f} /* mid-left */
|
||||
};
|
||||
|
||||
static void draw_keylist(gla2DDrawInfo *di, ListBase *keys, ListBase *blocks, float ypos)
|
||||
/* draw a simple diamond shape with OpenGL */
|
||||
void draw_keyframe_shape (float x, float y, float xscale, float hsize, short sel, short mode)
|
||||
{
|
||||
static GLuint displist1=0;
|
||||
static GLuint displist2=0;
|
||||
|
||||
/* initialise 2 display lists for diamond shape - one empty, one filled */
|
||||
if (displist1 == 0) {
|
||||
displist1= glGenLists(1);
|
||||
glNewList(displist1, GL_COMPILE);
|
||||
|
||||
glBegin(GL_LINE_LOOP);
|
||||
glVertex2fv(_unit_diamond_shape[0]);
|
||||
glVertex2fv(_unit_diamond_shape[1]);
|
||||
glVertex2fv(_unit_diamond_shape[2]);
|
||||
glVertex2fv(_unit_diamond_shape[3]);
|
||||
glEnd();
|
||||
glEndList();
|
||||
}
|
||||
if (displist2 == 0) {
|
||||
displist2= glGenLists(1);
|
||||
glNewList(displist2, GL_COMPILE);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glVertex2fv(_unit_diamond_shape[0]);
|
||||
glVertex2fv(_unit_diamond_shape[1]);
|
||||
glVertex2fv(_unit_diamond_shape[2]);
|
||||
glVertex2fv(_unit_diamond_shape[3]);
|
||||
glEnd();
|
||||
glEndList();
|
||||
}
|
||||
|
||||
/* adjust view transform before starting */
|
||||
glTranslatef(x, y, 0.0f);
|
||||
glScalef(1.0f/xscale*hsize, hsize, 1.0f);
|
||||
|
||||
/* anti-aliased lines for more consistent appearance */
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
|
||||
/* draw! */
|
||||
if ELEM(mode, KEYFRAME_SHAPE_INSIDE, KEYFRAME_SHAPE_BOTH) {
|
||||
/* interior - hardcoded colors (for selected and unselected only) */
|
||||
if (sel) UI_ThemeColorShade(TH_STRIP_SELECT, 50);
|
||||
else glColor3ub(0xE9, 0xE9, 0xE9);
|
||||
|
||||
glCallList(displist2);
|
||||
}
|
||||
|
||||
if ELEM(mode, KEYFRAME_SHAPE_FRAME, KEYFRAME_SHAPE_BOTH) {
|
||||
/* exterior - black frame */
|
||||
glColor3ub(0, 0, 0);
|
||||
|
||||
glCallList(displist1);
|
||||
}
|
||||
|
||||
glDisable(GL_LINE_SMOOTH);
|
||||
|
||||
/* restore view transform */
|
||||
glScalef(xscale/hsize, 1.0f/hsize, 1.0);
|
||||
glTranslatef(-x, -y, 0.0f);
|
||||
}
|
||||
|
||||
static void draw_keylist(View2D *v2d, ListBase *keys, ListBase *blocks, float ypos)
|
||||
{
|
||||
ActKeyColumn *ak;
|
||||
ActKeyBlock *ab;
|
||||
float xscale;
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
/* get View2D scaling factor */
|
||||
UI_view2d_getscale(v2d, &xscale, NULL);
|
||||
|
||||
/* draw keyblocks */
|
||||
if (blocks) {
|
||||
for (ab= blocks->first; ab; ab= ab->next) {
|
||||
@@ -292,18 +334,13 @@ static void draw_keylist(gla2DDrawInfo *di, ListBase *keys, ListBase *blocks, fl
|
||||
totCurves = (startCurves>endCurves)? endCurves: startCurves;
|
||||
|
||||
if (ab->totcurve >= totCurves) {
|
||||
int sc_xa, sc_xb, sc_ya, sc_yb;
|
||||
|
||||
/* get co-ordinates of block */
|
||||
gla2DDrawTranslatePt(di, ab->start, ypos, &sc_xa, &sc_ya);
|
||||
gla2DDrawTranslatePt(di, ab->end, ypos, &sc_xb, &sc_yb);
|
||||
|
||||
/* draw block */
|
||||
if (ab->sel)
|
||||
UI_ThemeColor4(TH_STRIP_SELECT);
|
||||
else
|
||||
UI_ThemeColor4(TH_STRIP);
|
||||
glRectf((float)sc_xa, (float)sc_ya-3, (float)sc_xb, (float)sc_yb+5);
|
||||
|
||||
glRectf(ab->start, ypos-5, ab->end, ypos+5);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -311,18 +348,28 @@ static void draw_keylist(gla2DDrawInfo *di, ListBase *keys, ListBase *blocks, fl
|
||||
/* draw keys */
|
||||
if (keys) {
|
||||
for (ak= keys->first; ak; ak= ak->next) {
|
||||
int sc_x, sc_y;
|
||||
/* draw using OpenGL - uglier but faster */
|
||||
// NOTE: a previous version of this didn't work nice for some intel cards
|
||||
draw_keyframe_shape(ak->cfra, ypos, xscale, 5.0f, (ak->sel & SELECT), KEYFRAME_SHAPE_BOTH);
|
||||
|
||||
#if 0 // OLD CODE
|
||||
//int sc_x, sc_y;
|
||||
|
||||
/* get co-ordinate to draw at */
|
||||
gla2DDrawTranslatePt(di, ak->cfra, ypos, &sc_x, &sc_y);
|
||||
//gla2DDrawTranslatePt(di, ak->cfra, ypos, &sc_x, &sc_y);
|
||||
|
||||
/* draw using icons - old way which is slower but more proven */
|
||||
if (ak->sel & SELECT) UI_icon_draw_aspect((float)sc_x-7, (float)sc_y-6, ICON_SPACE2, 1.0f);
|
||||
else UI_icon_draw_aspect((float)sc_x-7, (float)sc_y-6, ICON_SPACE3, 1.0f);
|
||||
//if (ak->sel & SELECT) UI_icon_draw_aspect((float)sc_x-7, (float)sc_y-6, ICON_SPACE2, 1.0f);
|
||||
//else UI_icon_draw_aspect((float)sc_x-7, (float)sc_y-6, ICON_SPACE3, 1.0f);
|
||||
#endif // OLD CODE
|
||||
#if 0 // NEW NON-WORKING CODE
|
||||
/* draw icon */
|
||||
// FIXME: this draws slightly wrong, as we need to apply some offset for icon, but that depends on scaling
|
||||
// so for now disabled
|
||||
//int icon = (ak->sel & SELECT) ? ICON_SPACE2 : ICON_SPACE3;
|
||||
//UI_icon_draw_aspect(ak->cfra, ypos-6, icon, 1.0f);
|
||||
#endif // NEW NON-WORKING CODE
|
||||
|
||||
/* draw using OpenGL - slightly uglier but faster */
|
||||
// NOTE: disabled for now, as some intel cards seem to have problems with this
|
||||
//draw_key_but(sc_x-5, sc_y-4, 11, 11, (ak->sel & SELECT));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -331,89 +378,86 @@ static void draw_keylist(gla2DDrawInfo *di, ListBase *keys, ListBase *blocks, fl
|
||||
|
||||
/* *************************** Channel Drawing Funcs *************************** */
|
||||
|
||||
void draw_scene_channel(gla2DDrawInfo *di, ActKeysInc *aki, Scene *sce, float ypos)
|
||||
void draw_scene_channel(View2D *v2d, bDopeSheet *ads, Scene *sce, float ypos)
|
||||
{
|
||||
ListBase keys = {0, 0};
|
||||
ListBase blocks = {0, 0};
|
||||
|
||||
scene_to_keylist(sce, &keys, &blocks, aki);
|
||||
draw_keylist(di, &keys, &blocks, ypos);
|
||||
scene_to_keylist(ads, sce, &keys, &blocks);
|
||||
draw_keylist(v2d, &keys, &blocks, ypos);
|
||||
|
||||
BLI_freelistN(&keys);
|
||||
BLI_freelistN(&blocks);
|
||||
}
|
||||
|
||||
void draw_object_channel(gla2DDrawInfo *di, ActKeysInc *aki, Object *ob, float ypos)
|
||||
void draw_object_channel(View2D *v2d, bDopeSheet *ads, Object *ob, float ypos)
|
||||
{
|
||||
ListBase keys = {0, 0};
|
||||
ListBase blocks = {0, 0};
|
||||
|
||||
ob_to_keylist(ob, &keys, &blocks, aki);
|
||||
draw_keylist(di, &keys, &blocks, ypos);
|
||||
ob_to_keylist(ads, ob, &keys, &blocks);
|
||||
draw_keylist(v2d, &keys, &blocks, ypos);
|
||||
|
||||
BLI_freelistN(&keys);
|
||||
BLI_freelistN(&blocks);
|
||||
}
|
||||
|
||||
void draw_fcurve_channel(gla2DDrawInfo *di, ActKeysInc *aki, FCurve *fcu, float ypos)
|
||||
void draw_fcurve_channel(View2D *v2d, AnimData *adt, FCurve *fcu, float ypos)
|
||||
{
|
||||
ListBase keys = {0, 0};
|
||||
ListBase blocks = {0, 0};
|
||||
|
||||
fcurve_to_keylist(fcu, &keys, &blocks, aki);
|
||||
draw_keylist(di, &keys, &blocks, ypos);
|
||||
fcurve_to_keylist(adt, fcu, &keys, &blocks);
|
||||
draw_keylist(v2d, &keys, &blocks, ypos);
|
||||
|
||||
BLI_freelistN(&keys);
|
||||
BLI_freelistN(&blocks);
|
||||
}
|
||||
|
||||
void draw_agroup_channel(gla2DDrawInfo *di, ActKeysInc *aki, bActionGroup *agrp, float ypos)
|
||||
void draw_agroup_channel(View2D *v2d, AnimData *adt, bActionGroup *agrp, float ypos)
|
||||
{
|
||||
ListBase keys = {0, 0};
|
||||
ListBase blocks = {0, 0};
|
||||
|
||||
agroup_to_keylist(agrp, &keys, &blocks, aki);
|
||||
draw_keylist(di, &keys, &blocks, ypos);
|
||||
agroup_to_keylist(adt, agrp, &keys, &blocks);
|
||||
draw_keylist(v2d, &keys, &blocks, ypos);
|
||||
|
||||
BLI_freelistN(&keys);
|
||||
BLI_freelistN(&blocks);
|
||||
}
|
||||
|
||||
void draw_action_channel(gla2DDrawInfo *di, ActKeysInc *aki, bAction *act, float ypos)
|
||||
void draw_action_channel(View2D *v2d, AnimData *adt, bAction *act, float ypos)
|
||||
{
|
||||
ListBase keys = {0, 0};
|
||||
ListBase blocks = {0, 0};
|
||||
|
||||
action_to_keylist(act, &keys, &blocks, aki);
|
||||
draw_keylist(di, &keys, &blocks, ypos);
|
||||
action_to_keylist(adt, act, &keys, &blocks);
|
||||
draw_keylist(v2d, &keys, &blocks, ypos);
|
||||
|
||||
BLI_freelistN(&keys);
|
||||
BLI_freelistN(&blocks);
|
||||
}
|
||||
|
||||
void draw_gpl_channel(gla2DDrawInfo *di, ActKeysInc *aki, bGPDlayer *gpl, float ypos)
|
||||
void draw_gpl_channel(View2D *v2d, bDopeSheet *ads, bGPDlayer *gpl, float ypos)
|
||||
{
|
||||
ListBase keys = {0, 0};
|
||||
|
||||
gpl_to_keylist(gpl, &keys, NULL, aki);
|
||||
draw_keylist(di, &keys, NULL, ypos);
|
||||
gpl_to_keylist(ads, gpl, &keys, NULL);
|
||||
draw_keylist(v2d, &keys, NULL, ypos);
|
||||
BLI_freelistN(&keys);
|
||||
}
|
||||
|
||||
/* *************************** Keyframe List Conversions *************************** */
|
||||
|
||||
void scene_to_keylist(Scene *sce, ListBase *keys, ListBase *blocks, ActKeysInc *aki)
|
||||
void scene_to_keylist(bDopeSheet *ads, Scene *sce, ListBase *keys, ListBase *blocks)
|
||||
{
|
||||
if (sce) {
|
||||
bDopeSheet *ads= (aki)? (aki->ads) : NULL;
|
||||
AnimData *adt;
|
||||
int filterflag;
|
||||
|
||||
/* 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;
|
||||
|
||||
@@ -423,7 +467,7 @@ void scene_to_keylist(Scene *sce, ListBase *keys, ListBase *blocks, ActKeysInc *
|
||||
|
||||
// TODO: when we adapt NLA system, this needs to be the NLA-scaled version
|
||||
if (adt->action)
|
||||
action_to_keylist(adt->action, keys, blocks, aki);
|
||||
action_to_keylist(adt, adt->action, keys, blocks);
|
||||
}
|
||||
|
||||
/* world animdata */
|
||||
@@ -432,17 +476,16 @@ void scene_to_keylist(Scene *sce, ListBase *keys, ListBase *blocks, ActKeysInc *
|
||||
|
||||
// TODO: when we adapt NLA system, this needs to be the NLA-scaled version
|
||||
if (adt->action)
|
||||
action_to_keylist(adt->action, keys, blocks, aki);
|
||||
action_to_keylist(adt, adt->action, keys, blocks);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ob_to_keylist(Object *ob, ListBase *keys, ListBase *blocks, ActKeysInc *aki)
|
||||
void ob_to_keylist(bDopeSheet *ads, Object *ob, ListBase *keys, ListBase *blocks)
|
||||
{
|
||||
Key *key= ob_get_key(ob);
|
||||
|
||||
if (ob) {
|
||||
bDopeSheet *ads= (aki)? (aki->ads) : NULL;
|
||||
int filterflag;
|
||||
|
||||
/* get filterflag */
|
||||
@@ -453,79 +496,18 @@ void ob_to_keylist(Object *ob, ListBase *keys, ListBase *blocks, ActKeysInc *aki
|
||||
|
||||
/* Add action keyframes */
|
||||
if (ob->adt && ob->adt->action)
|
||||
action_nlascaled_to_keylist(ob, ob->adt->action, keys, blocks, aki);
|
||||
action_to_keylist(ob->adt, ob->adt->action, keys, blocks);
|
||||
|
||||
/* Add shapekey keyframes (only if dopesheet allows, if it is available) */
|
||||
// TODO: when we adapt NLA system, this needs to be the NLA-scaled version
|
||||
if ((key && key->adt && key->adt->action) && !(filterflag & ADS_FILTER_NOSHAPEKEYS))
|
||||
action_to_keylist(key->adt->action, keys, blocks, aki);
|
||||
action_to_keylist(key->adt, key->adt->action, keys, blocks);
|
||||
|
||||
#if 0 // XXX old animation system
|
||||
/* Add material keyframes (only if dopesheet allows, if it is available) */
|
||||
if ((ob->totcol) && !(filterflag & ADS_FILTER_NOMAT)) {
|
||||
short a;
|
||||
|
||||
for (a=0; a<ob->totcol; a++) {
|
||||
Material *ma= give_current_material(ob, a);
|
||||
|
||||
if (ELEM(NULL, ma, ma->ipo) == 0)
|
||||
ipo_to_keylist(ma->ipo, keys, blocks, aki);
|
||||
}
|
||||
}
|
||||
|
||||
/* Add object data keyframes */
|
||||
switch (ob->type) {
|
||||
case OB_CAMERA: /* ------- Camera ------------ */
|
||||
{
|
||||
Camera *ca= (Camera *)ob->data;
|
||||
if ((ca->ipo) && !(filterflag & ADS_FILTER_NOCAM))
|
||||
ipo_to_keylist(ca->ipo, keys, blocks, aki);
|
||||
}
|
||||
break;
|
||||
case OB_LAMP: /* ---------- Lamp ----------- */
|
||||
{
|
||||
Lamp *la= (Lamp *)ob->data;
|
||||
if ((la->ipo) && !(filterflag & ADS_FILTER_NOLAM))
|
||||
ipo_to_keylist(la->ipo, keys, blocks, aki);
|
||||
}
|
||||
break;
|
||||
case OB_CURVE: /* ------- Curve ---------- */
|
||||
{
|
||||
Curve *cu= (Curve *)ob->data;
|
||||
if ((cu->ipo) && !(filterflag & ADS_FILTER_NOCUR))
|
||||
ipo_to_keylist(cu->ipo, keys, blocks, aki);
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif // XXX old animation system
|
||||
// TODO: restore materials, and object data, etc.
|
||||
}
|
||||
}
|
||||
|
||||
static short bezt_in_aki_range (ActKeysInc *aki, BezTriple *bezt)
|
||||
{
|
||||
/* when aki == NULL, we don't care about range */
|
||||
if (aki == NULL)
|
||||
return 1;
|
||||
|
||||
/* if start and end are both 0, then don't care about range */
|
||||
if (IS_EQ(aki->start, 0) && IS_EQ(aki->end, 0))
|
||||
return 1;
|
||||
|
||||
/* if nla-scaling is in effect, apply appropriate scaling adjustments */
|
||||
#if 0 // XXX this was from some buggy code... do not port for now
|
||||
if (aki->ob) {
|
||||
float frame= get_action_frame_inv(aki->ob, bezt->vec[1][0]);
|
||||
return IN_RANGE(frame, aki->start, aki->end);
|
||||
}
|
||||
else {
|
||||
/* check if in range */
|
||||
return IN_RANGE(bezt->vec[1][0], aki->start, aki->end);
|
||||
}
|
||||
#endif // XXX this was from some buggy code... do not port for now
|
||||
return 1;
|
||||
}
|
||||
|
||||
void fcurve_to_keylist(FCurve *fcu, ListBase *keys, ListBase *blocks, ActKeysInc *aki)
|
||||
void fcurve_to_keylist(AnimData *adt, FCurve *fcu, ListBase *keys, ListBase *blocks)
|
||||
{
|
||||
BezTriple *bezt;
|
||||
ActKeyColumn *ak, *ak2;
|
||||
@@ -533,15 +515,17 @@ void fcurve_to_keylist(FCurve *fcu, ListBase *keys, ListBase *blocks, ActKeysInc
|
||||
int v;
|
||||
|
||||
if (fcu && fcu->totvert && fcu->bezt) {
|
||||
/* apply NLA-mapping (if applicable) */
|
||||
if (adt)
|
||||
ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 1);
|
||||
|
||||
/* loop through beztriples, making ActKeys and ActKeyBlocks */
|
||||
bezt= fcu->bezt;
|
||||
|
||||
for (v=0; v < fcu->totvert; v++, bezt++) {
|
||||
/* only if keyframe is in range (optimisation) */
|
||||
if (bezt_in_aki_range(aki, bezt)) {
|
||||
add_bezt_to_keycolumnslist(keys, bezt);
|
||||
if (blocks) add_bezt_to_keyblockslist(blocks, fcu, v);
|
||||
}
|
||||
add_bezt_to_keycolumnslist(keys, bezt);
|
||||
if (blocks) add_bezt_to_keyblockslist(blocks, fcu, v);
|
||||
}
|
||||
|
||||
/* update the number of curves that elements have appeared in */
|
||||
@@ -577,65 +561,38 @@ void fcurve_to_keylist(FCurve *fcu, ListBase *keys, ListBase *blocks, ActKeysInc
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* unapply NLA-mapping if applicable */
|
||||
ANIM_nla_mapping_apply_fcurve(adt, fcu, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void agroup_to_keylist(bActionGroup *agrp, ListBase *keys, ListBase *blocks, ActKeysInc *aki)
|
||||
void agroup_to_keylist(AnimData *adt, bActionGroup *agrp, ListBase *keys, ListBase *blocks)
|
||||
{
|
||||
FCurve *fcu;
|
||||
|
||||
if (agrp) {
|
||||
/* loop through F-Curves */
|
||||
for (fcu= agrp->channels.first; fcu && fcu->grp==agrp; fcu= fcu->next) {
|
||||
fcurve_to_keylist(fcu, keys, blocks, aki);
|
||||
fcurve_to_keylist(adt, fcu, keys, blocks);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void action_to_keylist(bAction *act, ListBase *keys, ListBase *blocks, ActKeysInc *aki)
|
||||
void action_to_keylist(AnimData *adt, bAction *act, ListBase *keys, ListBase *blocks)
|
||||
{
|
||||
FCurve *fcu;
|
||||
|
||||
if (act) {
|
||||
/* loop through F-Curves */
|
||||
for (fcu= act->curves.first; fcu; fcu= fcu->next) {
|
||||
fcurve_to_keylist(fcu, keys, blocks, aki);
|
||||
fcurve_to_keylist(adt, fcu, keys, blocks);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void action_nlascaled_to_keylist(Object *ob, bAction *act, ListBase *keys, ListBase *blocks, ActKeysInc *aki)
|
||||
{
|
||||
FCurve *fcu;
|
||||
Object *oldob= NULL;
|
||||
|
||||
/* although apply and clearing NLA-scaling pre-post creating keylist does impact on performance,
|
||||
* the effects should be fairly minimal, as we're already going through the keyframes multiple times
|
||||
* already for blocks too...
|
||||
*/
|
||||
if (act) {
|
||||
/* if 'aki' is provided, store it's current ob to restore later as it might not be the same */
|
||||
if (aki) {
|
||||
oldob= aki->ob;
|
||||
aki->ob= ob;
|
||||
}
|
||||
|
||||
/* loop through F-Curves
|
||||
* - scaling correction only does times for center-points, so should be faster
|
||||
*/
|
||||
for (fcu= act->curves.first; fcu; fcu= fcu->next) {
|
||||
ANIM_nla_mapping_apply_fcurve(ob, fcu, 0, 1);
|
||||
fcurve_to_keylist(fcu, keys, blocks, aki);
|
||||
ANIM_nla_mapping_apply_fcurve(ob, fcu, 1, 1);
|
||||
}
|
||||
|
||||
/* if 'aki' is provided, restore ob */
|
||||
if (aki)
|
||||
aki->ob= oldob;
|
||||
}
|
||||
}
|
||||
|
||||
void gpl_to_keylist(bGPDlayer *gpl, ListBase *keys, ListBase *blocks, ActKeysInc *aki)
|
||||
void gpl_to_keylist(bDopeSheet *ads, bGPDlayer *gpl, ListBase *keys, ListBase *blocks)
|
||||
{
|
||||
bGPDframe *gpf;
|
||||
ActKeyColumn *ak;
|
||||
|
||||
@@ -128,6 +128,10 @@ static short agrp_keys_bezier_loop(BeztEditData *bed, bActionGroup *agrp, BeztEd
|
||||
{
|
||||
FCurve *fcu;
|
||||
|
||||
/* sanity check */
|
||||
if (agrp == NULL)
|
||||
return 0;
|
||||
|
||||
/* only iterate over the F-Curves that are in this group */
|
||||
for (fcu= agrp->channels.first; fcu && fcu->grp==agrp; fcu= fcu->next) {
|
||||
if (ANIM_fcurve_keys_bezier_loop(bed, fcu, bezt_ok, bezt_cb, fcu_cb))
|
||||
@@ -142,6 +146,10 @@ static short act_keys_bezier_loop(BeztEditData *bed, bAction *act, BeztEditFunc
|
||||
{
|
||||
FCurve *fcu;
|
||||
|
||||
/* sanity check */
|
||||
if (act == NULL)
|
||||
return 0;
|
||||
|
||||
/* just loop through all F-Curves */
|
||||
for (fcu= act->curves.first; fcu; fcu= fcu->next) {
|
||||
if (ANIM_fcurve_keys_bezier_loop(bed, fcu, bezt_ok, bezt_cb, fcu_cb))
|
||||
@@ -154,6 +162,10 @@ static short act_keys_bezier_loop(BeztEditData *bed, bAction *act, BeztEditFunc
|
||||
/* This function is used to loop over the keyframe data of an AnimData block */
|
||||
static short adt_keys_bezier_loop(BeztEditData *bed, AnimData *adt, BeztEditFunc bezt_ok, BeztEditFunc bezt_cb, FcuEditFunc fcu_cb, int filterflag)
|
||||
{
|
||||
/* sanity check */
|
||||
if (adt == NULL)
|
||||
return 0;
|
||||
|
||||
/* drivers or actions? */
|
||||
if (filterflag & ADS_FILTER_ONLYDRIVERS) {
|
||||
FCurve *fcu;
|
||||
@@ -178,6 +190,10 @@ static short ob_keys_bezier_loop(BeztEditData *bed, Object *ob, BeztEditFunc bez
|
||||
{
|
||||
Key *key= ob_get_key(ob);
|
||||
|
||||
/* sanity check */
|
||||
if (ob == NULL)
|
||||
return 0;
|
||||
|
||||
/* firstly, Object's own AnimData */
|
||||
if (ob->adt)
|
||||
adt_keys_bezier_loop(bed, ob->adt, bezt_ok, bezt_cb, fcu_cb, filterflag);
|
||||
@@ -194,7 +210,11 @@ static short ob_keys_bezier_loop(BeztEditData *bed, Object *ob, BeztEditFunc bez
|
||||
/* This function is used to loop over the keyframe data in a Scene */
|
||||
static short scene_keys_bezier_loop(BeztEditData *bed, Scene *sce, BeztEditFunc bezt_ok, BeztEditFunc bezt_cb, FcuEditFunc fcu_cb, int filterflag)
|
||||
{
|
||||
World *wo= sce->world;
|
||||
World *wo= (sce) ? sce->world : NULL;
|
||||
|
||||
/* sanity check */
|
||||
if (sce == NULL)
|
||||
return 0;
|
||||
|
||||
/* Scene's own animation */
|
||||
if (sce->adt)
|
||||
@@ -231,7 +251,7 @@ short ANIM_animchannel_keys_bezier_loop(BeztEditData *bed, bAnimListElem *ale, B
|
||||
return act_keys_bezier_loop(bed, (bAction *)ale->data, bezt_ok, bezt_cb, fcu_cb);
|
||||
|
||||
case ALE_OB: /* object */
|
||||
return ob_keys_bezier_loop(bed, (Object *)ale->data, bezt_ok, bezt_cb, fcu_cb, filterflag);
|
||||
return ob_keys_bezier_loop(bed, (Object *)ale->key_data, bezt_ok, bezt_cb, fcu_cb, filterflag);
|
||||
case ALE_SCE: /* scene */
|
||||
return scene_keys_bezier_loop(bed, (Scene *)ale->data, bezt_ok, bezt_cb, fcu_cb, filterflag);
|
||||
}
|
||||
|
||||
@@ -52,6 +52,8 @@
|
||||
#include "ED_keyframing.h"
|
||||
#include "ED_keyframes_edit.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
|
||||
/* This file contains code for various keyframe-editing tools which are 'destructive'
|
||||
* (i.e. they will modify the order of the keyframes, and change the size of the array).
|
||||
* While some of these tools may eventually be moved out into blenkernel, for now, it is
|
||||
|
||||
@@ -1,5 +1,30 @@
|
||||
/* Testing code for 2.5 animation system
|
||||
* Copyright 2009, Joshua Leung
|
||||
/**
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): Joshua Leung (full recode)
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -29,6 +54,7 @@
|
||||
#include "BKE_action.h"
|
||||
#include "BKE_constraint.h"
|
||||
#include "BKE_fcurve.h"
|
||||
#include "BKE_nla.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_utildefines.h"
|
||||
#include "BKE_context.h"
|
||||
@@ -697,9 +723,119 @@ static float visualkey_get_value (PointerRNA *ptr, PropertyRNA *prop, int array_
|
||||
|
||||
/* ------------------------- Insert Key API ------------------------- */
|
||||
|
||||
/* Secondary Keyframing API call:
|
||||
* Use this when validation of necessary animation data is not necessary, since an RNA-pointer to the necessary
|
||||
* data being keyframed, and a pointer to the F-Curve to use have both been provided.
|
||||
*
|
||||
* The flag argument is used for special settings that alter the behaviour of
|
||||
* the keyframe insertion. These include the 'visual' keyframing modes, quick refresh,
|
||||
* and extra keyframe filtering.
|
||||
*/
|
||||
short insert_keyframe_direct (PointerRNA ptr, PropertyRNA *prop, FCurve *fcu, float cfra, short flag)
|
||||
{
|
||||
float curval= 0.0f;
|
||||
|
||||
/* no F-Curve to add keyframe to? */
|
||||
if (fcu == NULL) {
|
||||
printf("ERROR: no F-Curve to add keyframes to \n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if no property given yet, try to validate from F-Curve info */
|
||||
if ((ptr.id.data == NULL) && (ptr.data==NULL)) {
|
||||
printf("ERROR: no RNA-pointer available to retrieve values for keyframing from\n");
|
||||
return 0;
|
||||
}
|
||||
if (prop == NULL) {
|
||||
PointerRNA tmp_ptr;
|
||||
|
||||
/* try to get property we should be affecting */
|
||||
if ((RNA_path_resolve(&ptr, fcu->rna_path, &tmp_ptr, &prop) == 0) || (prop == NULL)) {
|
||||
/* property not found... */
|
||||
char *idname= (ptr.id.data) ? ((ID *)ptr.id.data)->name : "<No ID-Pointer>";
|
||||
|
||||
printf("Insert Key: Could not insert keyframe, as RNA Path is invalid for the given ID (ID = %s, Path = %s)\n", idname, fcu->rna_path);
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
/* property found, so overwrite 'ptr' to make later code easier */
|
||||
ptr= tmp_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
/* set additional flags for the F-Curve (i.e. only integer values) */
|
||||
fcu->flag &= ~(FCURVE_INT_VALUES|FCURVE_DISCRETE_VALUES);
|
||||
switch (RNA_property_type(prop)) {
|
||||
case PROP_FLOAT:
|
||||
/* do nothing */
|
||||
break;
|
||||
case PROP_INT:
|
||||
/* do integer (only 'whole' numbers) interpolation between all points */
|
||||
fcu->flag |= FCURVE_INT_VALUES;
|
||||
break;
|
||||
default:
|
||||
/* do 'discrete' (i.e. enum, boolean values which cannot take any intermediate
|
||||
* values at all) interpolation between all points
|
||||
* - however, we must also ensure that evaluated values are only integers still
|
||||
*/
|
||||
fcu->flag |= (FCURVE_DISCRETE_VALUES|FCURVE_INT_VALUES);
|
||||
break;
|
||||
}
|
||||
|
||||
/* obtain value to give keyframe */
|
||||
if ( (flag & INSERTKEY_MATRIX) &&
|
||||
(visualkey_can_use(&ptr, prop)) )
|
||||
{
|
||||
/* visual-keying is only available for object and pchan datablocks, as
|
||||
* it works by keyframing using a value extracted from the final matrix
|
||||
* instead of using the kt system to extract a value.
|
||||
*/
|
||||
curval= visualkey_get_value(&ptr, prop, fcu->array_index);
|
||||
}
|
||||
else {
|
||||
/* read value from system */
|
||||
curval= setting_get_rna_value(&ptr, prop, fcu->array_index);
|
||||
}
|
||||
|
||||
/* only insert keyframes where they are needed */
|
||||
if (flag & INSERTKEY_NEEDED) {
|
||||
short insert_mode;
|
||||
|
||||
/* check whether this curve really needs a new keyframe */
|
||||
insert_mode= new_key_needed(fcu, cfra, curval);
|
||||
|
||||
/* insert new keyframe at current frame */
|
||||
if (insert_mode)
|
||||
insert_vert_fcurve(fcu, cfra, curval, (flag & INSERTKEY_FAST));
|
||||
|
||||
/* delete keyframe immediately before/after newly added */
|
||||
switch (insert_mode) {
|
||||
case KEYNEEDED_DELPREV:
|
||||
delete_fcurve_key(fcu, fcu->totvert-2, 1);
|
||||
break;
|
||||
case KEYNEEDED_DELNEXT:
|
||||
delete_fcurve_key(fcu, 1, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
/* only return success if keyframe added */
|
||||
if (insert_mode)
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
/* just insert keyframe */
|
||||
insert_vert_fcurve(fcu, cfra, curval, (flag & INSERTKEY_FAST));
|
||||
|
||||
/* return success */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* failed */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Main Keyframing API call:
|
||||
* Use this when validation of necessary animation data isn't necessary as it
|
||||
* already exists. It will insert a keyframe using the current value being keyframed.
|
||||
* Use this when validation of necessary animation data is necessary, since it may not exist yet.
|
||||
*
|
||||
* The flag argument is used for special settings that alter the behaviour of
|
||||
* the keyframe insertion. These include the 'visual' keyframing modes, quick refresh,
|
||||
@@ -719,102 +855,31 @@ short insert_keyframe (ID *id, bAction *act, const char group[], const char rna_
|
||||
}
|
||||
|
||||
/* get F-Curve - if no action is provided, keyframe to the default one attached to this ID-block */
|
||||
if (act == NULL)
|
||||
if (act == NULL) {
|
||||
AnimData *adt= BKE_animdata_from_id(id);
|
||||
|
||||
/* get action to add F-Curve+keyframe to */
|
||||
act= verify_adt_action(id, 1);
|
||||
|
||||
/* apply NLA-mapping to frame to use (if applicable) */
|
||||
cfra= BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP);
|
||||
}
|
||||
fcu= verify_fcurve(act, group, rna_path, array_index, 1);
|
||||
|
||||
/* only continue if we have an F-Curve to add keyframe to */
|
||||
if (fcu) {
|
||||
float curval= 0.0f;
|
||||
/* apply special time tweaking */
|
||||
// XXX check on this stuff...
|
||||
if (GS(id->name) == ID_OB) {
|
||||
//Object *ob= (Object *)id;
|
||||
|
||||
/* set additional flags for the F-Curve (i.e. only integer values) */
|
||||
fcu->flag &= ~(FCURVE_INT_VALUES|FCURVE_DISCRETE_VALUES);
|
||||
switch (RNA_property_type(prop)) {
|
||||
case PROP_FLOAT:
|
||||
/* do nothing */
|
||||
break;
|
||||
case PROP_INT:
|
||||
/* do integer (only 'whole' numbers) interpolation between all points */
|
||||
fcu->flag |= FCURVE_INT_VALUES;
|
||||
break;
|
||||
default:
|
||||
/* do 'discrete' (i.e. enum, boolean values which cannot take any intermediate
|
||||
* values at all) interpolation between all points
|
||||
* - however, we must also ensure that evaluated values are only integers still
|
||||
*/
|
||||
fcu->flag |= (FCURVE_DISCRETE_VALUES|FCURVE_INT_VALUES);
|
||||
break;
|
||||
}
|
||||
|
||||
/* apply special time tweaking */
|
||||
// XXX check on this stuff...
|
||||
if (GS(id->name) == ID_OB) {
|
||||
//Object *ob= (Object *)id;
|
||||
|
||||
/* apply NLA-scaling (if applicable) */
|
||||
//cfra= get_action_frame(ob, cfra);
|
||||
|
||||
/* ancient time-offset cruft */
|
||||
//if ( (ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)) ) {
|
||||
// /* actually frametofloat calc again! */
|
||||
// cfra-= give_timeoffset(ob)*scene->r.framelen;
|
||||
//}
|
||||
}
|
||||
|
||||
/* obtain value to give keyframe */
|
||||
if ( (flag & INSERTKEY_MATRIX) &&
|
||||
(visualkey_can_use(&ptr, prop)) )
|
||||
{
|
||||
/* visual-keying is only available for object and pchan datablocks, as
|
||||
* it works by keyframing using a value extracted from the final matrix
|
||||
* instead of using the kt system to extract a value.
|
||||
*/
|
||||
curval= visualkey_get_value(&ptr, prop, array_index);
|
||||
}
|
||||
else {
|
||||
/* read value from system */
|
||||
curval= setting_get_rna_value(&ptr, prop, array_index);
|
||||
}
|
||||
|
||||
/* only insert keyframes where they are needed */
|
||||
if (flag & INSERTKEY_NEEDED) {
|
||||
short insert_mode;
|
||||
|
||||
/* check whether this curve really needs a new keyframe */
|
||||
insert_mode= new_key_needed(fcu, cfra, curval);
|
||||
|
||||
/* insert new keyframe at current frame */
|
||||
if (insert_mode)
|
||||
insert_vert_fcurve(fcu, cfra, curval, (flag & INSERTKEY_FAST));
|
||||
|
||||
/* delete keyframe immediately before/after newly added */
|
||||
switch (insert_mode) {
|
||||
case KEYNEEDED_DELPREV:
|
||||
delete_fcurve_key(fcu, fcu->totvert-2, 1);
|
||||
break;
|
||||
case KEYNEEDED_DELNEXT:
|
||||
delete_fcurve_key(fcu, 1, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
/* only return success if keyframe added */
|
||||
if (insert_mode)
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
/* just insert keyframe */
|
||||
insert_vert_fcurve(fcu, cfra, curval, (flag & INSERTKEY_FAST));
|
||||
|
||||
/* return success */
|
||||
return 1;
|
||||
}
|
||||
/* ancient time-offset cruft */
|
||||
//if ( (ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)) ) {
|
||||
// /* actually frametofloat calc again! */
|
||||
// cfra-= give_timeoffset(ob)*scene->r.framelen;
|
||||
//}
|
||||
}
|
||||
|
||||
/* no F-Curve to add keyframes to */
|
||||
printf("ERROR: no F-Curve to add keyframes to \n");
|
||||
|
||||
/* return failure */
|
||||
return 0;
|
||||
/* insert keyframe */
|
||||
return insert_keyframe_direct(ptr, prop, fcu, cfra, flag);
|
||||
}
|
||||
|
||||
/* ************************************************** */
|
||||
@@ -839,6 +904,9 @@ short delete_keyframe (ID *id, bAction *act, const char group[], const char rna_
|
||||
/* if no action is provided, use the default one attached to this ID-block */
|
||||
AnimData *adt= BKE_animdata_from_id(id);
|
||||
act= adt->action;
|
||||
|
||||
/* apply NLA-mapping to frame to use (if applicable) */
|
||||
cfra= BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP);
|
||||
}
|
||||
/* we don't check the validity of the path here yet, but it should be ok... */
|
||||
fcu= verify_fcurve(act, group, rna_path, array_index, 0);
|
||||
@@ -852,9 +920,6 @@ short delete_keyframe (ID *id, bAction *act, const char group[], const char rna_
|
||||
if (GS(id->name) == ID_OB) {
|
||||
//Object *ob= (Object *)id;
|
||||
|
||||
/* apply NLA-scaling (if applicable) */
|
||||
// cfra= get_action_frame(ob, cfra);
|
||||
|
||||
/* ancient time-offset cruft */
|
||||
//if ( (ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)) ) {
|
||||
// /* actually frametofloat calc again! */
|
||||
@@ -1241,6 +1306,13 @@ static int insert_key_button_exec (bContext *C, wmOperator *op)
|
||||
|
||||
MEM_freeN(path);
|
||||
}
|
||||
else if (ptr.type == &RNA_NlaStrip) {
|
||||
/* handle special vars for NLA-strips */
|
||||
NlaStrip *strip= (NlaStrip *)ptr.data;
|
||||
FCurve *fcu= list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), 0);
|
||||
|
||||
success+= insert_keyframe_direct(ptr, prop, fcu, cfra, 0);
|
||||
}
|
||||
else {
|
||||
if (G.f & G_DEBUG)
|
||||
printf("Button Insert-Key: no path to property \n");
|
||||
@@ -1358,6 +1430,31 @@ void ANIM_OT_delete_keyframe_button (wmOperatorType *ot)
|
||||
|
||||
/* --------------- API/Per-Datablock Handling ------------------- */
|
||||
|
||||
/* Checks if some F-Curve has a keyframe for a given frame */
|
||||
short fcurve_frame_has_keyframe (FCurve *fcu, float frame, short filter)
|
||||
{
|
||||
/* quick sanity check */
|
||||
if (fcu == NULL)
|
||||
return 0;
|
||||
|
||||
/* we either include all regardless of muting, or only non-muted */
|
||||
if ((filter & ANIMFILTER_KEYS_MUTED) || (fcu->flag & FCURVE_MUTED)==0) {
|
||||
short replace = -1;
|
||||
int i = binarysearch_bezt_index(fcu->bezt, frame, fcu->totvert, &replace);
|
||||
|
||||
/* binarysearch_bezt_index will set replace to be 0 or 1
|
||||
* - obviously, 1 represents a match
|
||||
*/
|
||||
if (replace) {
|
||||
/* sanity check: 'i' may in rare cases exceed arraylen */
|
||||
if ((i >= 0) && (i < fcu->totvert))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Checks whether an Action has a keyframe for a given frame
|
||||
* Since we're only concerned whether a keyframe exists, we can simply loop until a match is found...
|
||||
*/
|
||||
@@ -1379,20 +1476,8 @@ short action_frame_has_keyframe (bAction *act, float frame, short filter)
|
||||
for (fcu= act->curves.first; fcu; fcu= fcu->next) {
|
||||
/* only check if there are keyframes (currently only of type BezTriple) */
|
||||
if (fcu->bezt && fcu->totvert) {
|
||||
/* we either include all regardless of muting, or only non-muted */
|
||||
if ((filter & ANIMFILTER_KEYS_MUTED) || (fcu->flag & FCURVE_MUTED)==0) {
|
||||
short replace = -1;
|
||||
int i = binarysearch_bezt_index(fcu->bezt, frame, fcu->totvert, &replace);
|
||||
|
||||
/* binarysearch_bezt_index will set replace to be 0 or 1
|
||||
* - obviously, 1 represents a match
|
||||
*/
|
||||
if (replace) {
|
||||
/* sanity check: 'i' may in rare cases exceed arraylen */
|
||||
if ((i >= 0) && (i < fcu->totvert))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (fcurve_frame_has_keyframe(fcu, frame, filter))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,30 @@
|
||||
/* Testing code for 2.5 animation system
|
||||
* Copyright 2009, Joshua Leung
|
||||
/**
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): Joshua Leung (full recode)
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -1060,6 +1085,9 @@ int modify_keyframes (bContext *C, ListBase *dsources, bAction *act, KeyingSet *
|
||||
case ID_MA: /* Material Keyframes */
|
||||
WM_event_add_notifier(C, NC_MATERIAL|ND_KEYS, ksp->id);
|
||||
break;
|
||||
default: /* Any keyframes */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1166,6 +1194,9 @@ int modify_keyframes (bContext *C, ListBase *dsources, bAction *act, KeyingSet *
|
||||
case ID_MA: /* Material Keyframes */
|
||||
WM_event_add_notifier(C, NC_MATERIAL|ND_KEYS, cks->id);
|
||||
break;
|
||||
default: /* Any keyframes */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -227,7 +227,7 @@ void poselib_validate_act (bAction *act)
|
||||
}
|
||||
|
||||
/* determine which frames have keys */
|
||||
action_to_keylist(act, &keys, NULL, NULL);
|
||||
action_to_keylist(NULL, act, &keys, NULL);
|
||||
|
||||
/* for each key, make sure there is a correspnding pose */
|
||||
for (ak= keys.first; ak; ak= ak->next) {
|
||||
|
||||
@@ -41,7 +41,7 @@ struct gla2DDrawInfo;
|
||||
struct Object;
|
||||
struct bActionGroup;
|
||||
struct FCurve;
|
||||
struct IpoCurve; // xxx
|
||||
struct FModifier;
|
||||
|
||||
/* ************************************************ */
|
||||
/* ANIMATION CHANNEL FILTERING */
|
||||
@@ -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 */
|
||||
@@ -106,6 +107,7 @@ typedef struct bAnimListElem {
|
||||
// XXX was ACTTYPE_*
|
||||
typedef enum eAnim_ChannelType {
|
||||
ANIMTYPE_NONE= 0,
|
||||
ANIMTYPE_ANIMDATA,
|
||||
ANIMTYPE_SPECIALDATA,
|
||||
|
||||
ANIMTYPE_SCENE,
|
||||
@@ -128,6 +130,9 @@ typedef enum eAnim_ChannelType {
|
||||
|
||||
ANIMTYPE_GPDATABLOCK,
|
||||
ANIMTYPE_GPLAYER,
|
||||
|
||||
ANIMTYPE_NLATRACK,
|
||||
ANIMTYPE_NLAACTION,
|
||||
} eAnim_ChannelType;
|
||||
|
||||
/* types of keyframe data in bAnimListElem */
|
||||
@@ -135,8 +140,8 @@ 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 */
|
||||
ALE_OB, /* Object summary */
|
||||
ALE_ACT, /* Action summary */
|
||||
@@ -156,7 +161,9 @@ typedef enum eAnimFilter_Flags {
|
||||
ANIMFILTER_CHANNELS = (1<<5), /* make list for interface drawing */
|
||||
ANIMFILTER_ACTGROUPED = (1<<6), /* belongs to the active actiongroup */
|
||||
ANIMFILTER_CURVEVISIBLE = (1<<7), /* F-Curve is visible for editing/viewing in Graph Editor */
|
||||
ANIMFILTER_ACTIVE = (1<<8), /* channel should be 'active' */ // FIXME: this is only relevant for F-Curves for now
|
||||
ANIMFILTER_ACTIVE = (1<<8), /* channel should be 'active' */
|
||||
ANIMFILTER_ANIMDATA = (1<<9), /* only return the underlying AnimData blocks (not the tracks, etc.) data comes from */
|
||||
ANIMFILTER_NLATRACKS = (1<<10), /* only include NLA-tracks */
|
||||
} eAnimFilter_Flags;
|
||||
|
||||
|
||||
@@ -202,6 +209,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 */
|
||||
@@ -217,6 +228,22 @@ typedef enum eAnimFilter_Flags {
|
||||
/* channel toggle-buttons */
|
||||
#define ACHANNEL_BUTTON_WIDTH 16
|
||||
|
||||
|
||||
/* -------------- NLA Channel Defines -------------- */
|
||||
|
||||
/* NLA channel heights */
|
||||
#define NLACHANNEL_FIRST -16
|
||||
#define NLACHANNEL_HEIGHT 24
|
||||
#define NLACHANNEL_HEIGHT_HALF 12
|
||||
#define NLACHANNEL_SKIP 2
|
||||
#define NLACHANNEL_STEP (NLACHANNEL_HEIGHT + NLACHANNEL_SKIP)
|
||||
|
||||
/* channel widths */
|
||||
#define NLACHANNEL_NAMEWIDTH 200
|
||||
|
||||
/* channel toggle-buttons */
|
||||
#define NLACHANNEL_BUTTON_WIDTH 16
|
||||
|
||||
/* ---------------- API -------------------- */
|
||||
|
||||
/* Obtain list of filtered Animation channels to operate on.
|
||||
@@ -245,7 +272,7 @@ short ANIM_animdata_context_getdata(bAnimContext *ac);
|
||||
void ANIM_deselect_anim_channels(void *data, short datatype, short test, short sel);
|
||||
|
||||
/* Set the 'active' channel of type channel_type, in the given action */
|
||||
void ANIM_set_active_channel(void *data, short datatype, int filter, void *channel_data, short channel_type);
|
||||
void ANIM_set_active_channel(bAnimContext *ac, void *data, short datatype, int filter, void *channel_data, short channel_type);
|
||||
|
||||
/* --------------- Settings and/or Defines -------------- */
|
||||
|
||||
@@ -282,6 +309,14 @@ void ANIM_draw_cfra(const struct bContext *C, struct View2D *v2d, short flag);
|
||||
/* main call to draw preview range curtains */
|
||||
void ANIM_draw_previewrange(const struct bContext *C, struct View2D *v2d);
|
||||
|
||||
/* ************************************************* */
|
||||
/* F-MODIFIER TOOLS */
|
||||
|
||||
struct uiLayout;
|
||||
|
||||
/* draw a given F-Modifier for some layout/UI-Block */
|
||||
void ANIM_uiTemplate_fmodifier_draw(struct uiLayout *layout, struct ID *id, ListBase *modifiers, struct FModifier *fcm);
|
||||
|
||||
/* ************************************************* */
|
||||
/* ASSORTED TOOLS */
|
||||
|
||||
@@ -299,19 +334,44 @@ void ipo_rainbow(int cur, int tot, float *out);
|
||||
/* ------------- NLA-Mapping ----------------------- */
|
||||
/* anim_draw.c */
|
||||
|
||||
/* Obtain the Object providing NLA-scaling for the given channel if applicable */
|
||||
struct Object *ANIM_nla_mapping_get(bAnimContext *ac, bAnimListElem *ale);
|
||||
/* Obtain the AnimData block providing NLA-scaling for the given channel if applicable */
|
||||
struct AnimData *ANIM_nla_mapping_get(bAnimContext *ac, bAnimListElem *ale);
|
||||
|
||||
/* Set/clear temporary mapping of coordinates from 'local-action' time to 'global-nla-scaled' time */
|
||||
void ANIM_nla_mapping_draw(struct gla2DDrawInfo *di, struct Object *ob, short restore);
|
||||
/* Set/clear temporary mapping of coordinates from 'local-action' time to 'global-nla-mapped' time */
|
||||
void ANIM_nla_mapping_draw(struct gla2DDrawInfo *di, struct AnimData *adt, short restore);
|
||||
|
||||
/* Apply/Unapply NLA mapping to all keyframes in the nominated IPO block */
|
||||
void ANIM_nla_mapping_apply_fcurve(struct Object *ob, struct FCurve *fcu, short restore, short only_keys);
|
||||
/* Apply/Unapply NLA mapping to all keyframes in the nominated F-Curve */
|
||||
void ANIM_nla_mapping_apply_fcurve(struct AnimData *adt, struct FCurve *fcu, short restore, short only_keys);
|
||||
|
||||
/* ------------- 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 -------- */
|
||||
|
||||
@@ -324,18 +384,6 @@ void ED_anim_object_flush_update(const struct bContext *C, struct Object *ob);
|
||||
void ANIM_action_to_pose_sync(struct Object *ob);
|
||||
void ANIM_pose_to_action_sync(struct Object *ob, struct ScrArea *sa);
|
||||
|
||||
|
||||
/* what types of animation data was changed (for sending notifiers from animation tools) */
|
||||
enum {
|
||||
ANIM_CHANGED_BOTH= 0,
|
||||
ANIM_CHANGED_KEYFRAMES_VALUES,
|
||||
ANIM_CHANGED_KEYFRAMES_SELECT,
|
||||
ANIM_CHANGED_CHANNELS
|
||||
} eAnimData_Changed;
|
||||
|
||||
/* Send notifiers on behalf of animation editing tools, based on various context info */
|
||||
void ANIM_animdata_send_notifiers(struct bContext *C, bAnimContext *ac, short data_changed);
|
||||
|
||||
/* ************************************************* */
|
||||
/* OPERATORS */
|
||||
|
||||
|
||||
@@ -30,15 +30,17 @@
|
||||
#ifndef ED_KEYFRAMES_DRAW_H
|
||||
#define ED_KEYFRAMES_DRAW_H
|
||||
|
||||
struct AnimData;
|
||||
struct BezTriple;
|
||||
struct FCurve;
|
||||
struct gla2DDrawInfo;
|
||||
struct bDopeSheet;
|
||||
struct bAction;
|
||||
struct bActionGroup;
|
||||
struct Object;
|
||||
struct ListBase;
|
||||
struct bGPDlayer;
|
||||
struct Scene;
|
||||
struct View2D;
|
||||
|
||||
/* ****************************** Base Structs ****************************** */
|
||||
|
||||
@@ -66,33 +68,38 @@ typedef struct ActKeyBlock {
|
||||
} ActKeyBlock;
|
||||
|
||||
|
||||
/* Inclusion-Range Limiting Struct (optional) */
|
||||
typedef struct ActKeysInc {
|
||||
struct bDopeSheet *ads; /* dopesheet data (for dopesheet mode) */
|
||||
struct Object *ob; /* owner object for NLA-scaling info (if Object channels, is just Object) */
|
||||
short actmode; /* mode of the Action Editor (-1 is for NLA) */
|
||||
|
||||
float start, end; /* frames (global-time) to only consider keys between */ // XXX not used anymore!
|
||||
} ActKeysInc;
|
||||
/* *********************** Keyframe Drawing ****************************** */
|
||||
|
||||
/* options for keyframe shape drawing */
|
||||
typedef enum eKeyframeShapeDrawOpts {
|
||||
/* only the border */
|
||||
KEYFRAME_SHAPE_FRAME = 0,
|
||||
/* only the inside filling */
|
||||
KEYFRAME_SHAPE_INSIDE,
|
||||
/* the whole thing */
|
||||
KEYFRAME_SHAPE_BOTH
|
||||
} eKeyframeShapeDrawOpts;
|
||||
|
||||
/* draw simple diamond-shape keyframe (with OpenGL) */
|
||||
void draw_keyframe_shape (float x, float y, float xscale, float hsize, short sel, short mode);
|
||||
|
||||
/* ******************************* Methods ****************************** */
|
||||
|
||||
/* Channel Drawing */
|
||||
void draw_fcurve_channel(struct gla2DDrawInfo *di, ActKeysInc *aki, struct FCurve *fcu, float ypos);
|
||||
void draw_agroup_channel(struct gla2DDrawInfo *di, ActKeysInc *aki, struct bActionGroup *agrp, float ypos);
|
||||
void draw_action_channel(struct gla2DDrawInfo *di, ActKeysInc *aki, struct bAction *act, float ypos);
|
||||
void draw_object_channel(struct gla2DDrawInfo *di, ActKeysInc *aki, struct Object *ob, float ypos);
|
||||
void draw_scene_channel(struct gla2DDrawInfo *di, ActKeysInc *aki, struct Scene *sce, float ypos);
|
||||
void draw_gpl_channel(struct gla2DDrawInfo *di, ActKeysInc *aki, struct bGPDlayer *gpl, float ypos);
|
||||
void draw_fcurve_channel(struct View2D *v2d, struct AnimData *adt, struct FCurve *fcu, float ypos);
|
||||
void draw_agroup_channel(struct View2D *v2d, struct AnimData *adt, struct bActionGroup *agrp, float ypos);
|
||||
void draw_action_channel(struct View2D *v2d, struct AnimData *adt, struct bAction *act, float ypos);
|
||||
void draw_object_channel(struct View2D *v2d, struct bDopeSheet *ads, struct Object *ob, float ypos);
|
||||
void draw_scene_channel(struct View2D *v2d, struct bDopeSheet *ads, struct Scene *sce, float ypos);
|
||||
void draw_gpl_channel(struct View2D *v2d, struct bDopeSheet *ads, struct bGPDlayer *gpl, float ypos);
|
||||
|
||||
/* Keydata Generation */
|
||||
void fcurve_to_keylist(struct FCurve *fcu, ListBase *keys, ListBase *blocks, ActKeysInc *aki);
|
||||
void agroup_to_keylist(struct bActionGroup *agrp, ListBase *keys, ListBase *blocks, ActKeysInc *aki);
|
||||
void action_to_keylist(struct bAction *act, ListBase *keys, ListBase *blocks, ActKeysInc *aki);
|
||||
void action_nlascaled_to_keylist(struct Object *ob, struct bAction *act, ListBase *keys, ListBase *blocks, ActKeysInc *aki);
|
||||
void ob_to_keylist(struct Object *ob, ListBase *keys, ListBase *blocks, ActKeysInc *aki);
|
||||
void scene_to_keylist(struct Scene *sce, ListBase *keys, ListBase *blocks, ActKeysInc *aki);
|
||||
void gpl_to_keylist(struct bGPDlayer *gpl, ListBase *keys, ListBase *blocks, ActKeysInc *aki);
|
||||
void fcurve_to_keylist(struct AnimData *adt, struct FCurve *fcu, ListBase *keys, ListBase *blocks);
|
||||
void agroup_to_keylist(struct AnimData *adt, struct bActionGroup *agrp, ListBase *keys, ListBase *blocks);
|
||||
void action_to_keylist(struct AnimData *adt, struct bAction *act, ListBase *keys, ListBase *blocks);
|
||||
void ob_to_keylist(struct bDopeSheet *ads, struct Object *ob, ListBase *keys, ListBase *blocks);
|
||||
void scene_to_keylist(struct bDopeSheet *ads, struct Scene *sce, ListBase *keys, ListBase *blocks);
|
||||
void gpl_to_keylist(struct bDopeSheet *ads, struct bGPDlayer *gpl, ListBase *keys, ListBase *blocks);
|
||||
|
||||
#endif /* ED_KEYFRAMES_DRAW_H */
|
||||
|
||||
|
||||
@@ -43,6 +43,9 @@ struct bConstraint;
|
||||
struct bContext;
|
||||
struct wmOperatorType;
|
||||
|
||||
struct PointerRNA;
|
||||
struct PropertyRNA;
|
||||
|
||||
/* ************ Keyframing Management **************** */
|
||||
|
||||
/* Get (or add relevant data to be able to do so) the Active Action for the given
|
||||
@@ -69,6 +72,16 @@ int insert_bezt_fcurve(struct FCurve *fcu, struct BezTriple *bezt);
|
||||
*/
|
||||
void insert_vert_fcurve(struct FCurve *fcu, float x, float y, short flag);
|
||||
|
||||
/* -------- */
|
||||
|
||||
/* Secondary Keyframing API calls:
|
||||
* Use this to insert a keyframe using the current value being keyframed, in the
|
||||
* nominated F-Curve (no creation of animation data performed). Returns success.
|
||||
*/
|
||||
short insert_keyframe_direct(struct PointerRNA ptr, struct PropertyRNA *prop, struct FCurve *fcu, float cfra, short flag);
|
||||
|
||||
|
||||
|
||||
/* -------- */
|
||||
|
||||
/* Main Keyframing API calls:
|
||||
@@ -186,6 +199,11 @@ void ANIM_OT_remove_driver_button(struct wmOperatorType *ot);
|
||||
|
||||
/* ************ Keyframe Checking ******************** */
|
||||
|
||||
/* Lesser Keyframe Checking API call:
|
||||
* - Used for the buttons to check for keyframes...
|
||||
*/
|
||||
short fcurve_frame_has_keyframe(struct FCurve *fcu, float frame, short filter);
|
||||
|
||||
/* Main Keyframe Checking API call:
|
||||
* Checks whether a keyframe exists for the given ID-block one the given frame.
|
||||
* - It is recommended to call this method over the other keyframe-checkers directly,
|
||||
|
||||
@@ -118,6 +118,7 @@ int ED_operator_node_active(struct bContext *C);
|
||||
int ED_operator_ipo_active(struct bContext *C);
|
||||
int ED_operator_sequencer_active(struct bContext *C);
|
||||
int ED_operator_image_active(struct bContext *C);
|
||||
int ED_operator_nla_active(struct bContext *C);
|
||||
int ED_operator_logic_active(struct bContext *C);
|
||||
|
||||
int ED_operator_object_active(struct bContext *C);
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
typedef struct ScreenAnimData {
|
||||
ARegion *ar; /* do not read from this, only for comparing if region exists */
|
||||
int redraws;
|
||||
int reverse;
|
||||
} ScreenAnimData;
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* $Id$
|
||||
* $Id: ED_transform.h 21450 2009-07-09 02:45:48Z theeth $
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_types.h"
|
||||
|
||||
#include "ED_keyframing.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
@@ -28,12 +30,15 @@
|
||||
void ui_but_anim_flag(uiBut *but, float cfra)
|
||||
{
|
||||
but->flag &= ~(UI_BUT_ANIMATED|UI_BUT_ANIMATED_KEY|UI_BUT_DRIVEN);
|
||||
|
||||
if(but->rnaprop && but->rnapoin.id.data) {
|
||||
|
||||
/* there must be some RNA-pointer + property combo for this button */
|
||||
if (but->rnaprop && but->rnapoin.id.data &&
|
||||
RNA_property_animateable(&but->rnapoin, but->rnaprop))
|
||||
{
|
||||
AnimData *adt= BKE_animdata_from_id(but->rnapoin.id.data);
|
||||
FCurve *fcu;
|
||||
char *path;
|
||||
|
||||
|
||||
if (adt) {
|
||||
if ((adt->action && adt->action->curves.first) || (adt->drivers.first)) {
|
||||
/* XXX this function call can become a performance bottleneck */
|
||||
@@ -47,7 +52,7 @@ void ui_but_anim_flag(uiBut *but, float cfra)
|
||||
if (fcu) {
|
||||
but->flag |= UI_BUT_ANIMATED;
|
||||
|
||||
if (on_keyframe_fcurve(fcu, cfra))
|
||||
if (fcurve_frame_has_keyframe(fcu, cfra, 0))
|
||||
but->flag |= UI_BUT_ANIMATED_KEY;
|
||||
}
|
||||
}
|
||||
@@ -111,7 +116,6 @@ void ui_but_anim_remove_driver(bContext *C)
|
||||
WM_operator_name_call(C, "ANIM_OT_remove_driver_button", WM_OP_INVOKE_DEFAULT, NULL);
|
||||
}
|
||||
|
||||
// TODO: refine the logic for adding/removing drivers...
|
||||
void ui_but_anim_menu(bContext *C, uiBut *but)
|
||||
{
|
||||
uiPopupMenu *pup;
|
||||
|
||||
@@ -505,7 +505,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;
|
||||
@@ -522,20 +525,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);
|
||||
@@ -1086,19 +1075,6 @@ void init_userdef_do_versions(void)
|
||||
SETCOL(btheme->ttime.cframe, 0x60, 0xc0, 0x40, 255);
|
||||
}
|
||||
}
|
||||
if ((G.main->versionfile < 245) || (G.main->versionfile == 245 && G.main->subversionfile < 11)) {
|
||||
bTheme *btheme;
|
||||
for (btheme= U.themes.first; btheme; btheme= btheme->next) {
|
||||
/* these should all use the same color */
|
||||
SETCOL(btheme->tv3d.cframe, 0x60, 0xc0, 0x40, 255);
|
||||
SETCOL(btheme->tipo.cframe, 0x60, 0xc0, 0x40, 255);
|
||||
SETCOL(btheme->tact.cframe, 0x60, 0xc0, 0x40, 255);
|
||||
SETCOL(btheme->tnla.cframe, 0x60, 0xc0, 0x40, 255);
|
||||
SETCOL(btheme->tseq.cframe, 0x60, 0xc0, 0x40, 255);
|
||||
SETCOL(btheme->tsnd.cframe, 0x60, 0xc0, 0x40, 255);
|
||||
SETCOL(btheme->ttime.cframe, 0x60, 0xc0, 0x40, 255);
|
||||
}
|
||||
}
|
||||
if ((G.main->versionfile < 245) || (G.main->versionfile == 245 && G.main->subversionfile < 13)) {
|
||||
bTheme *btheme;
|
||||
for (btheme= U.themes.first; btheme; btheme= btheme->next) {
|
||||
@@ -1221,6 +1197,13 @@ void init_userdef_do_versions(void)
|
||||
/* Graph Editor - Group Channel color */
|
||||
SETCOL(btheme->tipo.group, 79, 101, 73, 255);
|
||||
SETCOL(btheme->tipo.group_active, 135, 177, 125, 255);
|
||||
|
||||
/* Nla Editor - (Object) Channel color */
|
||||
SETCOL(btheme->tnla.ds_channel, 82, 96, 110, 255);
|
||||
SETCOL(btheme->tnla.ds_subchannel, 124, 137, 150, 255);
|
||||
/* NLA Editor - New Strip colors */
|
||||
SETCOL(btheme->tnla.strip, 12, 10, 10, 128);
|
||||
SETCOL(btheme->tnla.strip_select, 255, 140, 0, 255);
|
||||
}
|
||||
|
||||
/* adjust grease-pencil distances */
|
||||
|
||||
@@ -209,6 +209,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:
|
||||
{
|
||||
@@ -247,18 +264,21 @@ 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.xmin= 0.0f;
|
||||
v2d->cur.xmax= winx*style->panelzoom;
|
||||
|
||||
v2d->cur.ymax= 0.0f;
|
||||
v2d->cur.ymin= -winy*style->panelzoom;
|
||||
|
||||
v2d->cur.ymax= 0.0f;
|
||||
v2d->cur.ymin= -winy*style->panelzoom;
|
||||
}
|
||||
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 */
|
||||
|
||||
@@ -1460,7 +1460,9 @@ void ED_screen_full_prevspace(bContext *C)
|
||||
ed_screen_fullarea(C, sa);
|
||||
}
|
||||
|
||||
/* redraws: uses defines from stime->redraws */
|
||||
/* redraws: uses defines from stime->redraws
|
||||
* enable: 1 - forward on, -1 - backwards on, 0 - off
|
||||
*/
|
||||
void ED_screen_animation_timer(bContext *C, int redraws, int enable)
|
||||
{
|
||||
bScreen *screen= CTX_wm_screen(C);
|
||||
@@ -1477,6 +1479,7 @@ void ED_screen_animation_timer(bContext *C, int redraws, int enable)
|
||||
screen->animtimer= WM_event_add_window_timer(win, TIMER0, (1.0/FPS));
|
||||
sad->ar= CTX_wm_region(C);
|
||||
sad->redraws= redraws;
|
||||
sad->reverse= (enable < 0);
|
||||
screen->animtimer->customdata= sad;
|
||||
|
||||
}
|
||||
|
||||
@@ -166,6 +166,7 @@ int ED_operator_node_active(bContext *C)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// XXX rename
|
||||
int ED_operator_ipo_active(bContext *C)
|
||||
{
|
||||
return ed_spacetype_test(C, SPACE_IPO);
|
||||
@@ -181,6 +182,11 @@ int ED_operator_image_active(bContext *C)
|
||||
return ed_spacetype_test(C, SPACE_IMAGE);
|
||||
}
|
||||
|
||||
int ED_operator_nla_active(bContext *C)
|
||||
{
|
||||
return ed_spacetype_test(C, SPACE_NLA);
|
||||
}
|
||||
|
||||
int ED_operator_logic_active(bContext *C)
|
||||
{
|
||||
return ed_spacetype_test(C, SPACE_LOGIC);
|
||||
@@ -2070,19 +2076,40 @@ static int screen_animation_step(bContext *C, wmOperator *op, wmEvent *event)
|
||||
|
||||
if(scene->audio.flag & AUDIO_SYNC) {
|
||||
int step = floor(wt->duration * FPS);
|
||||
scene->r.cfra += step;
|
||||
if (sad->reverse) // XXX does this option work with audio?
|
||||
scene->r.cfra -= step;
|
||||
else
|
||||
scene->r.cfra += step;
|
||||
wt->duration -= ((float)step)/FPS;
|
||||
}
|
||||
else
|
||||
scene->r.cfra++;
|
||||
else {
|
||||
if (sad->reverse)
|
||||
scene->r.cfra--;
|
||||
else
|
||||
scene->r.cfra++;
|
||||
}
|
||||
|
||||
if (scene->r.psfra) {
|
||||
if(scene->r.cfra > scene->r.pefra)
|
||||
scene->r.cfra= scene->r.psfra;
|
||||
if (sad->reverse) {
|
||||
/* jump back to end */
|
||||
if (scene->r.psfra) {
|
||||
if(scene->r.cfra < scene->r.psfra)
|
||||
scene->r.cfra= scene->r.pefra;
|
||||
}
|
||||
else {
|
||||
if(scene->r.cfra < scene->r.sfra)
|
||||
scene->r.cfra= scene->r.efra;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(scene->r.cfra > scene->r.efra)
|
||||
scene->r.cfra= scene->r.sfra;
|
||||
/* jump back to start */
|
||||
if (scene->r.psfra) {
|
||||
if(scene->r.cfra > scene->r.pefra)
|
||||
scene->r.cfra= scene->r.psfra;
|
||||
}
|
||||
else {
|
||||
if(scene->r.cfra > scene->r.efra)
|
||||
scene->r.cfra= scene->r.sfra;
|
||||
}
|
||||
}
|
||||
|
||||
/* since we follow drawflags, we can't send notifier but tag regions ourselves */
|
||||
@@ -2130,8 +2157,9 @@ static int screen_animation_play(bContext *C, wmOperator *op, wmEvent *event)
|
||||
ED_screen_animation_timer(C, 0, 0);
|
||||
}
|
||||
else {
|
||||
/* todo: RNA properties to define play types */
|
||||
ED_screen_animation_timer(C, TIME_REGION|TIME_ALL_3D_WIN, 1);
|
||||
int mode= (RNA_boolean_get(op->ptr, "reverse")) ? -1 : 1;
|
||||
|
||||
ED_screen_animation_timer(C, TIME_REGION|TIME_ALL_3D_WIN, mode);
|
||||
|
||||
if(screen->animtimer) {
|
||||
wmTimer *wt= screen->animtimer;
|
||||
@@ -2155,7 +2183,7 @@ void SCREEN_OT_animation_play(wmOperatorType *ot)
|
||||
|
||||
ot->poll= ED_operator_screenactive;
|
||||
|
||||
|
||||
RNA_def_boolean(ot->srna, "reverse", 0, "Play in Reverse", "Animation is played backwards");
|
||||
}
|
||||
|
||||
/* ************** border select operator (template) ***************************** */
|
||||
|
||||
@@ -422,6 +422,8 @@ void draw_channel_names(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
|
||||
*/
|
||||
v2d->tot.ymin= (float)(-height);
|
||||
}
|
||||
/* need to do a view-sync here, so that the keys area doesn't jump around */
|
||||
UI_view2d_sync(NULL, ac->sa, v2d, V2D_VIEWSYNC_AREA_VERTICAL);
|
||||
|
||||
/* loop through channels, and set up drawing depending on their type */
|
||||
y= (float)ACHANNEL_FIRST;
|
||||
@@ -645,6 +647,11 @@ void draw_channel_names(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
|
||||
expand = ICON_TRIA_RIGHT;
|
||||
}
|
||||
|
||||
if (agrp->flag & AGRP_MUTED)
|
||||
mute = ICON_MUTE_IPO_ON;
|
||||
else
|
||||
mute = ICON_MUTE_IPO_OFF;
|
||||
|
||||
if (EDITABLE_AGRP(agrp))
|
||||
protect = ICON_UNLOCKED;
|
||||
else
|
||||
@@ -955,27 +962,8 @@ void draw_channel_names(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
|
||||
/* ************************************************************************* */
|
||||
/* Keyframes */
|
||||
|
||||
ActKeysInc *init_aki_data(bAnimContext *ac, bAnimListElem *ale)
|
||||
{
|
||||
static ActKeysInc aki;
|
||||
|
||||
/* no need to set settings if wrong context */
|
||||
if ((ac->data == NULL) || ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET)==0)
|
||||
return NULL;
|
||||
|
||||
/* if strip is mapped, store settings */
|
||||
aki.ob= ANIM_nla_mapping_get(ac, ale);
|
||||
|
||||
if (ac->datatype == ANIMCONT_DOPESHEET)
|
||||
aki.ads= (bDopeSheet *)ac->data;
|
||||
else
|
||||
aki.ads= NULL;
|
||||
aki.actmode= ac->datatype;
|
||||
|
||||
/* always return pointer... */
|
||||
return &aki;
|
||||
}
|
||||
|
||||
/* extra padding for lengths (to go under scrollers) */
|
||||
#define EXTRA_SCROLL_PAD 100.0f
|
||||
|
||||
/* draw keyframes in each channel */
|
||||
void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
|
||||
@@ -985,13 +973,11 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
|
||||
int filter;
|
||||
|
||||
View2D *v2d= &ar->v2d;
|
||||
Object *nob= NULL;
|
||||
gla2DDrawInfo *di;
|
||||
rcti scr_rct;
|
||||
bDopeSheet *ads= &saction->ads;
|
||||
AnimData *adt= NULL;
|
||||
|
||||
int act_start, act_end, dummy;
|
||||
float act_start, act_end, y;
|
||||
int height, items;
|
||||
float y, sta, end;
|
||||
|
||||
char col1[3], col2[3];
|
||||
char col1a[3], col2a[3];
|
||||
@@ -1001,6 +987,7 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
|
||||
/* get theme colors */
|
||||
UI_GetThemeColor3ubv(TH_BACK, col2);
|
||||
UI_GetThemeColor3ubv(TH_HILITE, col1);
|
||||
|
||||
UI_GetThemeColor3ubv(TH_GROUP, col2a);
|
||||
UI_GetThemeColor3ubv(TH_GROUP_ACTIVE, col1a);
|
||||
|
||||
@@ -1008,26 +995,14 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
|
||||
UI_GetThemeColor3ubv(TH_DOPESHEET_CHANNELSUBOB, col2b);
|
||||
|
||||
/* set view-mapping rect (only used for x-axis), for NLA-scaling mapping with less calculation */
|
||||
scr_rct.xmin= ar->winrct.xmin + ar->v2d.mask.xmin;
|
||||
scr_rct.ymin= ar->winrct.ymin + ar->v2d.mask.ymin;
|
||||
scr_rct.xmax= ar->winrct.xmin + ar->v2d.hor.xmax;
|
||||
scr_rct.ymax= ar->winrct.ymin + ar->v2d.mask.ymax;
|
||||
di= glaBegin2DDraw(&scr_rct, &v2d->cur);
|
||||
|
||||
/* if in NLA there's a strip active, map the view */
|
||||
if (ac->datatype == ANIMCONT_ACTION) {
|
||||
nob= ANIM_nla_mapping_get(ac, NULL);
|
||||
|
||||
if (nob)
|
||||
ANIM_nla_mapping_draw(di, nob, 0);
|
||||
adt= ANIM_nla_mapping_get(ac, NULL);
|
||||
|
||||
/* start and end of action itself */
|
||||
calc_action_range(ac->data, &sta, &end, 0);
|
||||
gla2DDrawTranslatePt(di, sta, 0.0f, &act_start, &dummy);
|
||||
gla2DDrawTranslatePt(di, end, 0.0f, &act_end, &dummy);
|
||||
|
||||
if (nob)
|
||||
ANIM_nla_mapping_draw(di, nob, 1);
|
||||
// TODO: this has not had scaling applied
|
||||
calc_action_range(ac->data, &act_start, &act_end, 0);
|
||||
}
|
||||
|
||||
/* build list of channels to draw */
|
||||
@@ -1058,7 +1033,7 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
|
||||
if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
|
||||
IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) )
|
||||
{
|
||||
int frame1_x, channel_y, sel=0;
|
||||
int sel=0;
|
||||
|
||||
/* determine if any need to draw channel */
|
||||
if (ale->datatype != ALE_NONE) {
|
||||
@@ -1097,8 +1072,6 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
|
||||
}
|
||||
|
||||
if (ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET)) {
|
||||
gla2DDrawTranslatePt(di, v2d->cur.xmin, y, &frame1_x, &channel_y);
|
||||
|
||||
switch (ale->type) {
|
||||
case ANIMTYPE_SCENE:
|
||||
case ANIMTYPE_OBJECT:
|
||||
@@ -1134,36 +1107,32 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
|
||||
}
|
||||
|
||||
/* draw region twice: firstly backdrop, then the current range */
|
||||
glRectf((float)frame1_x, (float)channel_y-ACHANNEL_HEIGHT_HALF, (float)v2d->hor.xmax, (float)channel_y+ACHANNEL_HEIGHT_HALF);
|
||||
glRectf(v2d->cur.xmin, (float)y-ACHANNEL_HEIGHT_HALF, v2d->cur.xmax+EXTRA_SCROLL_PAD, (float)y+ACHANNEL_HEIGHT_HALF);
|
||||
|
||||
if (ac->datatype == ANIMCONT_ACTION)
|
||||
glRectf((float)act_start, (float)channel_y-ACHANNEL_HEIGHT_HALF, (float)act_end, (float)channel_y+ACHANNEL_HEIGHT_HALF);
|
||||
glRectf(act_start, (float)y-ACHANNEL_HEIGHT_HALF, act_end, (float)y+ACHANNEL_HEIGHT_HALF);
|
||||
}
|
||||
else if (ac->datatype == ANIMCONT_SHAPEKEY) {
|
||||
gla2DDrawTranslatePt(di, 1, y, &frame1_x, &channel_y);
|
||||
|
||||
/* all frames that have a frame number less than one
|
||||
* get a desaturated orange background
|
||||
*/
|
||||
glColor4ub(col2[0], col2[1], col2[2], 0x22);
|
||||
glRectf(0.0f, (float)channel_y-ACHANNEL_HEIGHT_HALF, (float)frame1_x, (float)channel_y+ACHANNEL_HEIGHT_HALF);
|
||||
glRectf(0.0f, (float)y-ACHANNEL_HEIGHT_HALF, 1.0f, (float)y+ACHANNEL_HEIGHT_HALF);
|
||||
|
||||
/* frames one and higher get a saturated orange background */
|
||||
glColor4ub(col2[0], col2[1], col2[2], 0x44);
|
||||
glRectf((float)frame1_x, (float)channel_y-ACHANNEL_HEIGHT_HALF, (float)v2d->hor.xmax, (float)channel_y+ACHANNEL_HEIGHT_HALF);
|
||||
glRectf(1.0f, (float)y-ACHANNEL_HEIGHT_HALF, v2d->cur.xmax+EXTRA_SCROLL_PAD, (float)y+ACHANNEL_HEIGHT_HALF);
|
||||
}
|
||||
else if (ac->datatype == ANIMCONT_GPENCIL) {
|
||||
gla2DDrawTranslatePt(di, v2d->cur.xmin, y, &frame1_x, &channel_y);
|
||||
|
||||
/* frames less than one get less saturated background */
|
||||
if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22);
|
||||
else glColor4ub(col2[0], col2[1], col2[2], 0x22);
|
||||
glRectf(0.0f, (float)channel_y-ACHANNEL_HEIGHT_HALF, (float)frame1_x, (float)channel_y+ACHANNEL_HEIGHT_HALF);
|
||||
glRectf(0.0f, (float)y-ACHANNEL_HEIGHT_HALF, v2d->cur.xmin, (float)y+ACHANNEL_HEIGHT_HALF);
|
||||
|
||||
/* frames one and higher get a saturated background */
|
||||
if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x44);
|
||||
else glColor4ub(col2[0], col2[1], col2[2], 0x44);
|
||||
glRectf((float)frame1_x, (float)channel_y-ACHANNEL_HEIGHT_HALF, (float)v2d->hor.xmax, (float)channel_y+ACHANNEL_HEIGHT_HALF);
|
||||
glRectf(v2d->cur.xmin, (float)y-ACHANNEL_HEIGHT_HALF, v2d->cur.xmax+EXTRA_SCROLL_PAD, (float)y+ACHANNEL_HEIGHT_HALF);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1190,36 +1159,29 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
|
||||
{
|
||||
/* check if anything to show for this channel */
|
||||
if (ale->datatype != ALE_NONE) {
|
||||
ActKeysInc *aki= init_aki_data(ac, ale);
|
||||
nob= ANIM_nla_mapping_get(ac, ale);
|
||||
|
||||
if (nob)
|
||||
ANIM_nla_mapping_draw(di, nob, 0);
|
||||
adt= ANIM_nla_mapping_get(ac, ale);
|
||||
|
||||
/* draw 'keyframes' for each specific datatype */
|
||||
switch (ale->datatype) {
|
||||
case ALE_SCE:
|
||||
draw_scene_channel(di, aki, ale->key_data, y);
|
||||
draw_scene_channel(v2d, ads, ale->key_data, y);
|
||||
break;
|
||||
case ALE_OB:
|
||||
draw_object_channel(di, aki, ale->key_data, y);
|
||||
draw_object_channel(v2d, ads, ale->key_data, y);
|
||||
break;
|
||||
case ALE_ACT:
|
||||
draw_action_channel(di, aki, ale->key_data, y);
|
||||
draw_action_channel(v2d, adt, ale->key_data, y);
|
||||
break;
|
||||
case ALE_GROUP:
|
||||
draw_agroup_channel(di, aki, ale->data, y);
|
||||
draw_agroup_channel(v2d, adt, ale->data, y);
|
||||
break;
|
||||
case ALE_FCURVE:
|
||||
draw_fcurve_channel(di, aki, ale->key_data, y);
|
||||
draw_fcurve_channel(v2d, adt, ale->key_data, y);
|
||||
break;
|
||||
case ALE_GPFRAME:
|
||||
draw_gpl_channel(di, aki, ale->data, y);
|
||||
draw_gpl_channel(v2d, ads, ale->data, y);
|
||||
break;
|
||||
}
|
||||
|
||||
if (nob)
|
||||
ANIM_nla_mapping_draw(di, nob, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1231,16 +1193,11 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
|
||||
|
||||
/* black line marking 'current frame' for Time-Slide transform mode */
|
||||
if (saction->flag & SACTION_MOVING) {
|
||||
int frame1_x;
|
||||
|
||||
gla2DDrawTranslatePt(di, saction->timeslide, 0, &frame1_x, &dummy);
|
||||
cpack(0x0);
|
||||
glColor3f(0.0f, 0.0f, 0.0f);
|
||||
|
||||
glBegin(GL_LINES);
|
||||
glVertex2f((float)frame1_x, (float)v2d->mask.ymin - 100);
|
||||
glVertex2f((float)frame1_x, (float)v2d->mask.ymax);
|
||||
glVertex2f(saction->timeslide, v2d->cur.ymin-EXTRA_SCROLL_PAD);
|
||||
glVertex2f(saction->timeslide, v2d->cur.ymax);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
glaEnd2DDraw(di);
|
||||
}
|
||||
|
||||
@@ -67,6 +67,7 @@
|
||||
#include "BKE_fcurve.h"
|
||||
#include "BKE_key.h"
|
||||
#include "BKE_material.h"
|
||||
#include "BKE_nla.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_report.h"
|
||||
@@ -111,16 +112,16 @@ static void get_keyframe_extents (bAnimContext *ac, float *min, float *max)
|
||||
if (anim_data.first) {
|
||||
/* go through channels, finding max extents */
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
Object *nob= ANIM_nla_mapping_get(ac, ale);
|
||||
AnimData *adt= ANIM_nla_mapping_get(ac, ale);
|
||||
FCurve *fcu= (FCurve *)ale->key_data;
|
||||
float tmin, tmax;
|
||||
|
||||
/* get range and apply necessary scaling before */
|
||||
calc_fcurve_range(fcu, &tmin, &tmax);
|
||||
|
||||
if (nob) {
|
||||
tmin= get_action_frame_inv(nob, tmin);
|
||||
tmax= get_action_frame_inv(nob, tmax);
|
||||
if (adt) {
|
||||
tmin= BKE_nla_tweakedit_remap(adt, tmin, NLATIME_CONVERT_MAP);
|
||||
tmax= BKE_nla_tweakedit_remap(adt, tmax, NLATIME_CONVERT_MAP);
|
||||
}
|
||||
|
||||
/* try to set cur using these values, if they're more extreme than previously set values */
|
||||
@@ -180,7 +181,7 @@ void ACT_OT_previewrange_set (wmOperatorType *ot)
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= actkeys_previewrange_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= ED_operator_action_active;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -213,7 +214,7 @@ static int actkeys_viewall_exec(bContext *C, wmOperator *op)
|
||||
/* do View2D syncing */
|
||||
UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
/* just redraw this view */
|
||||
ED_area_tag_redraw(CTX_wm_area(C));
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
@@ -227,7 +228,7 @@ void ACT_OT_view_all (wmOperatorType *ot)
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= actkeys_viewall_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= ED_operator_action_active;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -300,21 +301,18 @@ static int actkeys_copy_exec(bContext *C, wmOperator *op)
|
||||
}
|
||||
}
|
||||
|
||||
/* set notifier that things have changed */
|
||||
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void ACT_OT_keyframes_copy (wmOperatorType *ot)
|
||||
void ACT_OT_copy (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Copy Keyframes";
|
||||
ot->idname= "ACT_OT_keyframes_copy";
|
||||
ot->idname= "ACT_OT_copy";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= actkeys_copy_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= ED_operator_action_active;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -344,21 +342,21 @@ static int actkeys_paste_exec(bContext *C, wmOperator *op)
|
||||
/* validate keyframes after editing */
|
||||
ANIM_editkeyframes_refresh(&ac);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
|
||||
/* set notifier that keyframes have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void ACT_OT_keyframes_paste (wmOperatorType *ot)
|
||||
void ACT_OT_paste (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Paste Keyframes";
|
||||
ot->idname= "ACT_OT_keyframes_paste";
|
||||
ot->idname= "ACT_OT_paste";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= actkeys_paste_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= ED_operator_action_active;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -399,14 +397,14 @@ static void insert_action_keys(bAnimContext *ac, short mode)
|
||||
|
||||
/* insert keyframes */
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
//Object *nob= ANIM_nla_mapping_get(ac, ale);
|
||||
AnimData *adt= ANIM_nla_mapping_get(ac, ale);
|
||||
FCurve *fcu= (FCurve *)ale->key_data;
|
||||
|
||||
/* adjust current frame for NLA-scaling */
|
||||
//if (nob)
|
||||
// cfra= get_action_frame(nob, CFRA);
|
||||
//else
|
||||
// cfra= (float)CFRA;
|
||||
if (adt)
|
||||
cfra= BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
|
||||
else
|
||||
cfra= (float)CFRA;
|
||||
|
||||
/* if there's an id */
|
||||
if (ale->id)
|
||||
@@ -431,31 +429,31 @@ static int actkeys_insertkey_exec(bContext *C, wmOperator *op)
|
||||
if (ac.datatype == ANIMCONT_GPENCIL)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
/* get snapping mode */
|
||||
/* what channels to affect? */
|
||||
mode= RNA_enum_get(op->ptr, "type");
|
||||
|
||||
/* snap keyframes */
|
||||
/* insert keyframes */
|
||||
insert_action_keys(&ac, mode);
|
||||
|
||||
/* validate keyframes after editing */
|
||||
ANIM_editkeyframes_refresh(&ac);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
|
||||
/* set notifier that keyframes have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void ACT_OT_keyframes_insert (wmOperatorType *ot)
|
||||
void ACT_OT_insert_keyframe (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Insert Keyframes";
|
||||
ot->idname= "ACT_OT_keyframes_insert";
|
||||
ot->idname= "ACT_OT_insert_keyframe";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke= WM_menu_invoke;
|
||||
ot->exec= actkeys_insertkey_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= ED_operator_action_active;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -507,8 +505,8 @@ static int actkeys_duplicate_exec(bContext *C, wmOperator *op)
|
||||
/* validate keyframes after editing */
|
||||
ANIM_editkeyframes_refresh(&ac);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
|
||||
/* set notifier that keyframes have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
|
||||
|
||||
return OPERATOR_FINISHED; // xxx - start transform
|
||||
}
|
||||
@@ -523,16 +521,16 @@ static int actkeys_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *event)
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void ACT_OT_keyframes_duplicate (wmOperatorType *ot)
|
||||
void ACT_OT_duplicate (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Duplicate Keyframes";
|
||||
ot->idname= "ACT_OT_keyframes_duplicate";
|
||||
ot->idname= "ACT_OT_duplicate";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke= actkeys_duplicate_invoke;
|
||||
ot->exec= actkeys_duplicate_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= ED_operator_action_active;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -584,22 +582,22 @@ static int actkeys_delete_exec(bContext *C, wmOperator *op)
|
||||
/* validate keyframes after editing */
|
||||
ANIM_editkeyframes_refresh(&ac);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
|
||||
/* set notifier that keyframes have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void ACT_OT_keyframes_delete (wmOperatorType *ot)
|
||||
void ACT_OT_delete (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Delete Keyframes";
|
||||
ot->idname= "ACT_OT_keyframes_delete";
|
||||
ot->idname= "ACT_OT_delete";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke= WM_operator_confirm;
|
||||
ot->exec= actkeys_delete_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= ED_operator_action_active;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -647,22 +645,22 @@ static int actkeys_clean_exec(bContext *C, wmOperator *op)
|
||||
/* validate keyframes after editing */
|
||||
ANIM_editkeyframes_refresh(&ac);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
|
||||
/* set notifier that keyframes have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void ACT_OT_keyframes_clean (wmOperatorType *ot)
|
||||
void ACT_OT_clean (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Clean Keyframes";
|
||||
ot->idname= "ACT_OT_keyframes_clean";
|
||||
ot->idname= "ACT_OT_clean";
|
||||
|
||||
/* api callbacks */
|
||||
//ot->invoke= // XXX we need that number popup for this!
|
||||
ot->exec= actkeys_clean_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= ED_operator_action_active;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -771,21 +769,21 @@ static int actkeys_sample_exec(bContext *C, wmOperator *op)
|
||||
/* validate keyframes after editing */
|
||||
ANIM_editkeyframes_refresh(&ac);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
|
||||
/* set notifier that keyframes have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void ACT_OT_keyframes_sample (wmOperatorType *ot)
|
||||
void ACT_OT_sample (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Sample Keyframes";
|
||||
ot->idname= "ACT_OT_keyframes_sample";
|
||||
ot->idname= "ACT_OT_sample";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= actkeys_sample_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= ED_operator_action_active;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -846,22 +844,22 @@ static int actkeys_expo_exec(bContext *C, wmOperator *op)
|
||||
/* validate keyframes after editing */
|
||||
ANIM_editkeyframes_refresh(&ac);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
|
||||
/* set notifier that keyframe properties have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_PROP, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void ACT_OT_keyframes_extrapolation_type_set (wmOperatorType *ot)
|
||||
void ACT_OT_extrapolation_type (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Set Keyframe Extrapolation";
|
||||
ot->idname= "ACT_OT_keyframes_extrapolation_type_set";
|
||||
ot->idname= "ACT_OT_extrapolation_type";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke= WM_menu_invoke;
|
||||
ot->exec= actkeys_expo_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= ED_operator_action_active;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -916,22 +914,22 @@ static int actkeys_ipo_exec(bContext *C, wmOperator *op)
|
||||
/* validate keyframes after editing */
|
||||
ANIM_editkeyframes_refresh(&ac);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
|
||||
/* set notifier that keyframe properties have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_PROP, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void ACT_OT_keyframes_interpolation_type (wmOperatorType *ot)
|
||||
void ACT_OT_interpolation_type (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Set Keyframe Interpolation";
|
||||
ot->idname= "ACT_OT_keyframes_interpolation_type";
|
||||
ot->idname= "ACT_OT_interpolation_type";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke= WM_menu_invoke;
|
||||
ot->exec= actkeys_ipo_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= ED_operator_action_active;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -1004,22 +1002,22 @@ static int actkeys_handletype_exec(bContext *C, wmOperator *op)
|
||||
/* validate keyframes after editing */
|
||||
ANIM_editkeyframes_refresh(&ac);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
|
||||
/* set notifier that keyframe properties have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_PROP, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void ACT_OT_keyframes_handle_type_set (wmOperatorType *ot)
|
||||
void ACT_OT_handle_type (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Set Keyframe Handle Type";
|
||||
ot->idname= "ACT_OT_keyframes_handle_type_set";
|
||||
ot->idname= "ACT_OT_handle_type";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke= WM_menu_invoke;
|
||||
ot->exec= actkeys_handletype_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= ED_operator_action_active;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -1031,10 +1029,10 @@ void ACT_OT_keyframes_handle_type_set (wmOperatorType *ot)
|
||||
/* ************************************************************************** */
|
||||
/* TRANSFORM STUFF */
|
||||
|
||||
/* ***************** Snap Current Frame Operator *********************** */
|
||||
/* ***************** Jump to Selected Frames Operator *********************** */
|
||||
|
||||
/* snap current-frame indicator to 'average time' of selected keyframe */
|
||||
static int actkeys_cfrasnap_exec(bContext *C, wmOperator *op)
|
||||
static int actkeys_framejump_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
bAnimContext ac;
|
||||
ListBase anim_data= {NULL, NULL};
|
||||
@@ -1053,8 +1051,17 @@ static int actkeys_cfrasnap_exec(bContext *C, wmOperator *op)
|
||||
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVESONLY);
|
||||
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
|
||||
|
||||
for (ale= anim_data.first; ale; ale= ale->next)
|
||||
ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, bezt_calc_average, NULL);
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
AnimData *adt= ANIM_nla_mapping_get(&ac, ale);
|
||||
|
||||
if (adt) {
|
||||
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
|
||||
ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, bezt_calc_average, NULL);
|
||||
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
|
||||
}
|
||||
else
|
||||
ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, bezt_calc_average, NULL);
|
||||
}
|
||||
|
||||
BLI_freelistN(&anim_data);
|
||||
|
||||
@@ -1070,15 +1077,15 @@ static int actkeys_cfrasnap_exec(bContext *C, wmOperator *op)
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void ACT_OT_keyframes_cfrasnap (wmOperatorType *ot)
|
||||
void ACT_OT_frame_jump (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Snap Current Frame to Keys";
|
||||
ot->idname= "ACT_OT_keyframes_cfrasnap";
|
||||
ot->name= "Jump to Frame";
|
||||
ot->idname= "ACT_OT_frame_jump";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= actkeys_cfrasnap_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->exec= actkeys_framejump_exec;
|
||||
ot->poll= ED_operator_action_active;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -1124,12 +1131,12 @@ static void snap_action_keys(bAnimContext *ac, short mode)
|
||||
|
||||
/* snap keyframes */
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
Object *nob= ANIM_nla_mapping_get(ac, ale);
|
||||
AnimData *adt= ANIM_nla_mapping_get(ac, ale);
|
||||
|
||||
if (nob) {
|
||||
ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 0, 1);
|
||||
if (adt) {
|
||||
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
|
||||
ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, edit_cb, calchandles_fcurve);
|
||||
ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 1, 1);
|
||||
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
|
||||
}
|
||||
//else if (ale->type == ACTTYPE_GPLAYER)
|
||||
// snap_gplayer_frames(ale->data, mode);
|
||||
@@ -1159,22 +1166,22 @@ static int actkeys_snap_exec(bContext *C, wmOperator *op)
|
||||
/* validate keyframes after editing */
|
||||
ANIM_editkeyframes_refresh(&ac);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
|
||||
/* set notifier that keyframes have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void ACT_OT_keyframes_snap (wmOperatorType *ot)
|
||||
void ACT_OT_snap (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Snap Keys";
|
||||
ot->idname= "ACT_OT_keyframes_snap";
|
||||
ot->idname= "ACT_OT_snap";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke= WM_menu_invoke;
|
||||
ot->exec= actkeys_snap_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= ED_operator_action_active;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -1187,10 +1194,10 @@ void ACT_OT_keyframes_snap (wmOperatorType *ot)
|
||||
|
||||
/* defines for mirror keyframes tool */
|
||||
EnumPropertyItem prop_actkeys_mirror_types[] = {
|
||||
{ACTKEYS_MIRROR_CFRA, "CFRA", 0, "Current frame", ""},
|
||||
{ACTKEYS_MIRROR_YAXIS, "YAXIS", 0, "Vertical Axis", ""},
|
||||
{ACTKEYS_MIRROR_XAXIS, "XAXIS", 0, "Horizontal Axis", ""},
|
||||
{ACTKEYS_MIRROR_MARKER, "MARKER", 0, "First Selected Marker", ""},
|
||||
{ACTKEYS_MIRROR_CFRA, "CFRA", 0, "By Times over Current frame", ""},
|
||||
{ACTKEYS_MIRROR_YAXIS, "YAXIS", 0, "By Times over Time=0", ""},
|
||||
{ACTKEYS_MIRROR_XAXIS, "XAXIS", 0, "By Values over Value=0", ""},
|
||||
{ACTKEYS_MIRROR_MARKER, "MARKER", 0, "By Times over First Selected Marker", ""},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
@@ -1240,12 +1247,12 @@ static void mirror_action_keys(bAnimContext *ac, short mode)
|
||||
|
||||
/* mirror keyframes */
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
Object *nob= ANIM_nla_mapping_get(ac, ale);
|
||||
AnimData *adt= ANIM_nla_mapping_get(ac, ale);
|
||||
|
||||
if (nob) {
|
||||
ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 0, 1);
|
||||
if (adt) {
|
||||
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
|
||||
ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, edit_cb, calchandles_fcurve);
|
||||
ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 1, 1);
|
||||
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
|
||||
}
|
||||
//else if (ale->type == ACTTYPE_GPLAYER)
|
||||
// snap_gplayer_frames(ale->data, mode);
|
||||
@@ -1275,22 +1282,22 @@ static int actkeys_mirror_exec(bContext *C, wmOperator *op)
|
||||
/* validate keyframes after editing */
|
||||
ANIM_editkeyframes_refresh(&ac);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
|
||||
/* set notifier that keyframes have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void ACT_OT_keyframes_mirror (wmOperatorType *ot)
|
||||
void ACT_OT_mirror (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Mirror Keys";
|
||||
ot->idname= "ACT_OT_keyframes_mirror";
|
||||
ot->idname= "ACT_OT_mirror";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke= WM_menu_invoke;
|
||||
ot->exec= actkeys_mirror_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= ED_operator_action_active;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
|
||||
@@ -48,9 +48,12 @@
|
||||
|
||||
#include "ED_anim_api.h"
|
||||
#include "ED_screen.h"
|
||||
#include "ED_transform.h"
|
||||
#include "ED_types.h"
|
||||
#include "ED_util.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
|
||||
@@ -63,1494 +66,183 @@
|
||||
|
||||
#include "action_intern.h"
|
||||
|
||||
enum {
|
||||
B_REDR= 0,
|
||||
} eActHeader_Events;
|
||||
|
||||
/* ********************************************************* */
|
||||
/* Menu Defines... */
|
||||
|
||||
/* button events */
|
||||
enum {
|
||||
B_REDR = 0,
|
||||
B_ACTCOPYKEYS,
|
||||
B_ACTPASTEKEYS,
|
||||
} eActHeader_ButEvents;
|
||||
|
||||
/* ------------------------------- */
|
||||
/* enums declaring constants that are used as menu event codes */
|
||||
|
||||
enum {
|
||||
ACTMENU_VIEW_CENTERVIEW= 0,
|
||||
ACTMENU_VIEW_AUTOUPDATE,
|
||||
ACTMENU_VIEW_PLAY3D,
|
||||
ACTMENU_VIEW_PLAYALL,
|
||||
ACTMENU_VIEW_ALL,
|
||||
ACTMENU_VIEW_MAXIMIZE,
|
||||
ACTMENU_VIEW_LOCK,
|
||||
ACTMENU_VIEW_SLIDERS,
|
||||
ACTMENU_VIEW_NEXTMARKER,
|
||||
ACTMENU_VIEW_PREVMARKER,
|
||||
ACTMENU_VIEW_NEXTKEYFRAME,
|
||||
ACTMENU_VIEW_PREVKEYFRAME,
|
||||
ACTMENU_VIEW_TIME,
|
||||
ACTMENU_VIEW_NOHIDE,
|
||||
ACTMENU_VIEW_FRANUM,
|
||||
ACTMENU_VIEW_TRANSDELDUPS,
|
||||
ACTMENU_VIEW_HORIZOPTIMISE,
|
||||
ACTMENU_VIEW_GCOLORS,
|
||||
ACTMENU_VIEW_PREVRANGESET,
|
||||
ACTMENU_VIEW_PREVRANGECLEAR,
|
||||
ACTMENU_VIEW_PREVRANGEAUTO
|
||||
};
|
||||
|
||||
enum {
|
||||
ACTMENU_SEL_BORDER = 0,
|
||||
ACTMENU_SEL_BORDERC,
|
||||
ACTMENU_SEL_BORDERM,
|
||||
ACTMENU_SEL_ALL_KEYS,
|
||||
ACTMENU_SEL_ALL_CHAN,
|
||||
ACTMENU_SEL_ALL_MARKERS,
|
||||
ACTMENU_SEL_INVERSE_KEYS,
|
||||
ACTMENU_SEL_INVERSE_MARKERS,
|
||||
ACTMENU_SEL_INVERSE_CHANNELS,
|
||||
ACTMENU_SEL_LEFTKEYS,
|
||||
ACTMENU_SEL_RIGHTKEYS
|
||||
};
|
||||
|
||||
enum {
|
||||
ACTMENU_SEL_COLUMN_KEYS = 1,
|
||||
ACTMENU_SEL_COLUMN_CFRA,
|
||||
ACTMENU_SEL_COLUMN_MARKERSCOLUMN,
|
||||
ACTMENU_SEL_COLUMN_MARKERSBETWEEN
|
||||
};
|
||||
|
||||
enum {
|
||||
ACTMENU_CHANNELS_OPENLEVELS = 0,
|
||||
ACTMENU_CHANNELS_CLOSELEVELS,
|
||||
ACTMENU_CHANNELS_EXPANDALL,
|
||||
ACTMENU_CHANNELS_SHOWACHANS,
|
||||
ACTMENU_CHANNELS_DELETE
|
||||
};
|
||||
|
||||
enum {
|
||||
ACTMENU_CHANNELS_CHANPOS_MOVE_CHANNEL_UP = 0,
|
||||
ACTMENU_CHANNELS_CHANPOS_MOVE_CHANNEL_DOWN,
|
||||
ACTMENU_CHANNELS_CHANPOS_MOVE_CHANNEL_TOP,
|
||||
ACTMENU_CHANNELS_CHANPOS_MOVE_CHANNEL_BOTTOM
|
||||
};
|
||||
|
||||
enum {
|
||||
ACTMENU_CHANNELS_GROUP_ADD_TOACTIVE = 0,
|
||||
ACTMENU_CHANNELS_GROUP_ADD_TONEW,
|
||||
ACTMENU_CHANNELS_GROUP_REMOVE,
|
||||
ACTMENU_CHANNELS_GROUP_SYNCPOSE
|
||||
};
|
||||
|
||||
enum {
|
||||
ACTMENU_CHANNELS_SETTINGS_TOGGLE = 0,
|
||||
ACTMENU_CHANNELS_SETTINGS_ENABLE,
|
||||
ACTMENU_CHANNELS_SETTINGS_DISABLE,
|
||||
};
|
||||
|
||||
enum {
|
||||
ACTMENU_KEY_DUPLICATE = 0,
|
||||
ACTMENU_KEY_DELETE,
|
||||
ACTMENU_KEY_CLEAN,
|
||||
ACTMENU_KEY_SAMPLEKEYS,
|
||||
ACTMENU_KEY_INSERTKEY
|
||||
};
|
||||
|
||||
enum {
|
||||
ACTMENU_KEY_TRANSFORM_MOVE = 0,
|
||||
ACTMENU_KEY_TRANSFORM_SCALE,
|
||||
ACTMENU_KEY_TRANSFORM_SLIDE,
|
||||
ACTMENU_KEY_TRANSFORM_EXTEND
|
||||
};
|
||||
|
||||
enum {
|
||||
ACTMENU_KEY_HANDLE_AUTO = 0,
|
||||
ACTMENU_KEY_HANDLE_ALIGN,
|
||||
ACTMENU_KEY_HANDLE_FREE,
|
||||
ACTMENU_KEY_HANDLE_VECTOR
|
||||
};
|
||||
|
||||
enum {
|
||||
ACTMENU_KEY_INTERP_CONST = 0,
|
||||
ACTMENU_KEY_INTERP_LINEAR,
|
||||
ACTMENU_KEY_INTERP_BEZIER
|
||||
};
|
||||
|
||||
enum {
|
||||
ACTMENU_KEY_EXTEND_CONST = 0,
|
||||
ACTMENU_KEY_EXTEND_EXTRAPOLATION,
|
||||
ACTMENU_KEY_EXTEND_CYCLIC,
|
||||
ACTMENU_KEY_EXTEND_CYCLICEXTRAPOLATION
|
||||
};
|
||||
|
||||
enum {
|
||||
ACTMENU_KEY_SNAP_NEARFRAME = 1,
|
||||
ACTMENU_KEY_SNAP_CURFRAME,
|
||||
ACTMENU_KEY_SNAP_NEARMARK,
|
||||
ACTMENU_KEY_SNAP_NEARTIME,
|
||||
ACTMENU_KEY_SNAP_CFRA2KEY,
|
||||
};
|
||||
|
||||
enum {
|
||||
ACTMENU_KEY_MIRROR_CURFRAME = 1,
|
||||
ACTMENU_KEY_MIRROR_YAXIS,
|
||||
ACTMENU_KEY_MIRROR_XAXIS,
|
||||
ACTMENU_KEY_MIRROR_MARKER
|
||||
};
|
||||
|
||||
enum {
|
||||
ACTMENU_MARKERS_ADD = 0,
|
||||
ACTMENU_MARKERS_DUPLICATE,
|
||||
ACTMENU_MARKERS_DELETE,
|
||||
ACTMENU_MARKERS_NAME,
|
||||
ACTMENU_MARKERS_MOVE,
|
||||
ACTMENU_MARKERS_LOCALADD,
|
||||
ACTMENU_MARKERS_LOCALRENAME,
|
||||
ACTMENU_MARKERS_LOCALDELETE,
|
||||
ACTMENU_MARKERS_LOCALMOVE
|
||||
};
|
||||
|
||||
/* ------------------------------- */
|
||||
/* macros for easier state testing (only for use here) */
|
||||
|
||||
/* test if active action editor is showing any markers */
|
||||
#if 0
|
||||
#define SACTION_HASMARKERS \
|
||||
((saction->action && saction->action->markers.first) \
|
||||
|| (scene->markers.first))
|
||||
#endif
|
||||
|
||||
/* need to find out how to get scene from context */
|
||||
#define SACTION_HASMARKERS (saction->action && saction->action->markers.first)
|
||||
|
||||
/* ------------------------------- */
|
||||
|
||||
/* *************************************************************** */
|
||||
/* menus */
|
||||
|
||||
/* Key menu --------------------------- */
|
||||
|
||||
static void do_keymenu_transformmenu(bContext *C, void *arg, int event)
|
||||
static void act_viewmenu(bContext *C, uiLayout *layout, void *arg_unused)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case ACTMENU_KEY_TRANSFORM_MOVE:
|
||||
//transform_action_keys('g', 0);
|
||||
break;
|
||||
case ACTMENU_KEY_TRANSFORM_SCALE:
|
||||
//transform_action_keys('s', 0);
|
||||
break;
|
||||
case ACTMENU_KEY_TRANSFORM_SLIDE:
|
||||
//transform_action_keys('t', 0);
|
||||
break;
|
||||
case ACTMENU_KEY_TRANSFORM_EXTEND:
|
||||
//transform_action_keys('e', 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uiBlock *action_keymenu_transformmenu(bContext *C, ARegion *ar, void *arg_unused)
|
||||
{
|
||||
uiBlock *block;
|
||||
short yco= 0, menuwidth=120;
|
||||
bScreen *sc= CTX_wm_screen(C);
|
||||
ScrArea *sa= CTX_wm_area(C);
|
||||
SpaceAction *sact= (SpaceAction*)CTX_wm_space_data(C);
|
||||
PointerRNA spaceptr;
|
||||
|
||||
block= uiBeginBlock(C, ar, "action_keymenu_transformmenu", UI_EMBOSSP);
|
||||
uiBlockSetButmFunc(block, do_keymenu_transformmenu, NULL);
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Grab/Move|G", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_KEY_TRANSFORM_MOVE, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Grab/Extend from Frame|E", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_KEY_TRANSFORM_EXTEND, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Scale|S", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_KEY_TRANSFORM_SCALE, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Time Slide|T", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_KEY_TRANSFORM_SLIDE, "");
|
||||
/* retrieve state */
|
||||
RNA_pointer_create(&sc->id, &RNA_SpaceDopeSheetEditor, sact, &spaceptr);
|
||||
|
||||
uiBlockSetDirection(block, UI_RIGHT);
|
||||
/* create menu */
|
||||
//uiItemO(layout, NULL, ICON_MENU_PANEL, "ACT_OT_properties");
|
||||
|
||||
uiTextBoundsBlock(block, 60);
|
||||
uiEndBlock(C, block);
|
||||
//uiItemS(layout);
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
static void do_keymenu_snapmenu(bContext *C, void *arg, int event)
|
||||
{
|
||||
switch(event)
|
||||
{
|
||||
case ACTMENU_KEY_SNAP_NEARFRAME:
|
||||
case ACTMENU_KEY_SNAP_CURFRAME:
|
||||
case ACTMENU_KEY_SNAP_NEARMARK:
|
||||
case ACTMENU_KEY_SNAP_NEARTIME:
|
||||
//snap_action_keys(event);
|
||||
break;
|
||||
|
||||
case ACTMENU_KEY_SNAP_CFRA2KEY:
|
||||
//snap_cfra_action();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uiBlock *action_keymenu_snapmenu(bContext *C, ARegion *ar, void *arg_unused)
|
||||
{
|
||||
SpaceAction *saction= (SpaceAction*)CTX_wm_space_data(C);
|
||||
uiBlock *block;
|
||||
short yco= 0, menuwidth=120;
|
||||
|
||||
uiItemR(layout, NULL, 0, &spaceptr, "show_cframe_indicator", 0, 0, 0);
|
||||
uiItemR(layout, NULL, 0, &spaceptr, "show_sliders", 0, 0, 0);
|
||||
uiItemR(layout, NULL, 0, &spaceptr, "automerge_keyframes", 0, 0, 0);
|
||||
|
||||
block= uiBeginBlock(C, ar, "action_keymenu_snapmenu", UI_EMBOSSP);
|
||||
uiBlockSetButmFunc(block, do_keymenu_snapmenu, NULL);
|
||||
|
||||
if (saction->flag & SACTION_DRAWTIME) {
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Key -> Nearest Second|Shift S, 1", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_KEY_SNAP_NEARTIME, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Key -> Current Time|Shift S, 2", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_KEY_SNAP_CURFRAME, "");
|
||||
|
||||
}
|
||||
else {
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Key -> Nearest Frame|Shift S, 1", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_KEY_SNAP_NEARFRAME, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Key -> Current Frame|Shift S, 2", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_KEY_SNAP_CURFRAME, "");
|
||||
}
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Key -> Nearest Marker|Shift S, 3", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_KEY_SNAP_NEARMARK, "");
|
||||
|
||||
uiDefBut(block, SEPR, 0, "", 0, yco-=6,
|
||||
menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Current Frame -> Key|Ctrl Shift S", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_KEY_SNAP_NEARMARK, "");
|
||||
if (sact->flag & SACTION_DRAWTIME)
|
||||
uiItemO(layout, "Show Frames", 0, "ANIM_OT_time_toggle");
|
||||
else
|
||||
uiItemO(layout, "Show Seconds", 0, "ANIM_OT_time_toggle");
|
||||
|
||||
uiBlockSetDirection(block, UI_RIGHT);
|
||||
uiItemS(layout);
|
||||
|
||||
uiTextBoundsBlock(block, 60);
|
||||
uiEndBlock(C, block);
|
||||
uiItemO(layout, NULL, 0, "ANIM_OT_previewrange_set");
|
||||
uiItemO(layout, NULL, 0, "ANIM_OT_previewrange_clear");
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
static void do_keymenu_mirrormenu(bContext *C, void *arg, int event)
|
||||
{
|
||||
switch(event)
|
||||
{
|
||||
case ACTMENU_KEY_MIRROR_CURFRAME:
|
||||
case ACTMENU_KEY_MIRROR_YAXIS:
|
||||
//mirror_action_keys(event);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static uiBlock *action_keymenu_mirrormenu(bContext *C, ARegion *ar, void *arg_unused)
|
||||
{
|
||||
uiBlock *block;
|
||||
short yco= 0, menuwidth=120;
|
||||
uiItemO(layout, NULL, 0, "ACT_OT_previewrange_set");
|
||||
|
||||
block= uiBeginBlock(C, ar, "action_keymenu_mirrormenu", UI_EMBOSSP);
|
||||
uiBlockSetButmFunc(block, do_keymenu_mirrormenu, NULL);
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Current Frame|Shift M, 1", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_KEY_MIRROR_CURFRAME, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Vertical Axis|Shift M, 2", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_KEY_MIRROR_YAXIS, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Horizontal Axis|Shift M, 3", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_KEY_MIRROR_XAXIS, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Selected Marker|Shift M, 4", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_KEY_MIRROR_MARKER, "");
|
||||
uiItemS(layout);
|
||||
|
||||
uiBlockSetDirection(block, UI_RIGHT);
|
||||
uiItemO(layout, NULL, 0, "ACT_OT_frame_jump");
|
||||
|
||||
uiTextBoundsBlock(block, 60);
|
||||
uiEndBlock(C, block);
|
||||
uiItemO(layout, NULL, 0, "ACT_OT_view_all");
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
static void do_keymenu_handlemenu(bContext *C, void *arg, int event)
|
||||
{
|
||||
switch (event) {
|
||||
case ACTMENU_KEY_HANDLE_AUTO:
|
||||
//sethandles_action_keys(HD_AUTO);
|
||||
break;
|
||||
|
||||
case ACTMENU_KEY_HANDLE_ALIGN:
|
||||
case ACTMENU_KEY_HANDLE_FREE:
|
||||
/* OK, this is kinda dumb, need to fix the
|
||||
* toggle crap in sethandles_ipo_keys()
|
||||
*/
|
||||
//sethandles_action_keys(HD_ALIGN);
|
||||
break;
|
||||
|
||||
case ACTMENU_KEY_HANDLE_VECTOR:
|
||||
//sethandles_action_keys(HD_VECT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uiBlock *action_keymenu_handlemenu(bContext *C, ARegion *ar, void *arg_unused)
|
||||
{
|
||||
uiBlock *block;
|
||||
short yco= 0, menuwidth=120;
|
||||
|
||||
block= uiBeginBlock(C, ar, "action_keymenu_handlemenu", UI_EMBOSSP);
|
||||
uiBlockSetButmFunc(block, do_keymenu_handlemenu, NULL);
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Auto|Shift H", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_KEY_HANDLE_AUTO, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Aligned|H", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_KEY_HANDLE_ALIGN, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Free|H", 0, yco-=20, menuwidth,
|
||||
19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_KEY_HANDLE_FREE, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Vector|V", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_KEY_HANDLE_VECTOR, "");
|
||||
|
||||
uiBlockSetDirection(block, UI_RIGHT);
|
||||
|
||||
uiTextBoundsBlock(block, 60);
|
||||
uiEndBlock(C, block);
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
static void do_keymenu_extendmenu(bContext *C, void *arg, int event)
|
||||
{
|
||||
switch(event)
|
||||
{
|
||||
case ACTMENU_KEY_EXTEND_CONST:
|
||||
//action_set_ipo_flags(SET_EXTEND_MENU, SET_EXTEND_CONSTANT);
|
||||
break;
|
||||
case ACTMENU_KEY_EXTEND_EXTRAPOLATION:
|
||||
//action_set_ipo_flags(SET_EXTEND_MENU, SET_EXTEND_EXTRAPOLATION);
|
||||
break;
|
||||
case ACTMENU_KEY_EXTEND_CYCLIC:
|
||||
//action_set_ipo_flags(SET_EXTEND_MENU, SET_EXTEND_CYCLIC);
|
||||
break;
|
||||
case ACTMENU_KEY_EXTEND_CYCLICEXTRAPOLATION:
|
||||
//action_set_ipo_flags(SET_EXTEND_MENU, SET_EXTEND_CYCLICEXTRAPOLATION);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uiBlock *action_keymenu_extendmenu(bContext *C, ARegion *ar, void *arg_unused)
|
||||
{
|
||||
uiBlock *block;
|
||||
short yco= 0, menuwidth=120;
|
||||
|
||||
block= uiBeginBlock(C, ar, "action_keymenu_extendmenu", UI_EMBOSSP);
|
||||
uiBlockSetButmFunc(block, do_keymenu_extendmenu, NULL);
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Constant", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_KEY_EXTEND_CONST, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Extrapolation", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_KEY_EXTEND_EXTRAPOLATION, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Cyclic", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_KEY_EXTEND_CYCLIC, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Cyclic Extrapolation", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_KEY_EXTEND_CYCLICEXTRAPOLATION, "");
|
||||
|
||||
uiBlockSetDirection(block, UI_RIGHT);
|
||||
|
||||
uiTextBoundsBlock(block, 60);
|
||||
uiEndBlock(C, block);
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
static void do_keymenu_intpolmenu(bContext *C, void *arg, int event)
|
||||
{
|
||||
switch(event)
|
||||
{
|
||||
case ACTMENU_KEY_INTERP_CONST:
|
||||
//action_set_ipo_flags(SET_IPO_MENU, SET_IPO_CONSTANT);
|
||||
break;
|
||||
case ACTMENU_KEY_INTERP_LINEAR:
|
||||
//action_set_ipo_flags(SET_IPO_MENU, SET_IPO_LINEAR);
|
||||
break;
|
||||
case ACTMENU_KEY_INTERP_BEZIER:
|
||||
//action_set_ipo_flags(SET_IPO_MENU, SET_IPO_BEZIER);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uiBlock *action_keymenu_intpolmenu(bContext *C, ARegion *ar, void *arg_unused)
|
||||
{
|
||||
uiBlock *block;
|
||||
short yco= 0, menuwidth=120;
|
||||
|
||||
block= uiBeginBlock(C, ar, "action_keymenu_intpolmenu", UI_EMBOSSP);
|
||||
uiBlockSetButmFunc(block, do_keymenu_intpolmenu, NULL);
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Constant|Shift T, 1", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_KEY_INTERP_CONST, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Linear|Shift T, 2", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_KEY_INTERP_LINEAR, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Bezier|Shift T, 3", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_KEY_INTERP_BEZIER, "");
|
||||
|
||||
uiBlockSetDirection(block, UI_RIGHT);
|
||||
|
||||
uiTextBoundsBlock(block, 60);
|
||||
uiEndBlock(C, block);
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
static void do_action_keymenu(bContext *C, void *arg, int event)
|
||||
{
|
||||
SpaceAction *saction= (SpaceAction*)CTX_wm_space_data(C);
|
||||
bAction *act;
|
||||
//Key *key;
|
||||
|
||||
if (!saction) return;
|
||||
|
||||
act = saction->action;
|
||||
//key = get_action_mesh_key();
|
||||
|
||||
switch(event)
|
||||
{
|
||||
case ACTMENU_KEY_DUPLICATE:
|
||||
//duplicate_action_keys();
|
||||
break;
|
||||
case ACTMENU_KEY_DELETE:
|
||||
//delete_action_keys();
|
||||
break;
|
||||
case ACTMENU_KEY_CLEAN:
|
||||
//clean_action();
|
||||
break;
|
||||
case ACTMENU_KEY_SAMPLEKEYS:
|
||||
//sample_action_keys();
|
||||
break;
|
||||
case ACTMENU_KEY_INSERTKEY:
|
||||
//insertkey_action();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uiBlock *action_keymenu(bContext *C, ARegion *ar, void *arg_unused)
|
||||
{
|
||||
ScrArea *curarea= CTX_wm_area(C);
|
||||
uiBlock *block;
|
||||
short yco= 0, menuwidth=120;
|
||||
|
||||
block= uiBeginBlock(C, ar, "action_keymenu", UI_EMBOSSP);
|
||||
|
||||
|
||||
uiBlockSetButmFunc(block, do_action_keymenu, NULL);
|
||||
|
||||
uiDefIconTextBlockBut(block, action_keymenu_transformmenu,
|
||||
NULL, ICON_RIGHTARROW_THIN, "Transform", 0, yco-=20, 120, 20, "");
|
||||
|
||||
uiDefIconTextBlockBut(block, action_keymenu_snapmenu,
|
||||
NULL, ICON_RIGHTARROW_THIN, "Snap", 0, yco-=20, 120, 20, "");
|
||||
|
||||
uiDefIconTextBlockBut(block, action_keymenu_mirrormenu,
|
||||
NULL, ICON_RIGHTARROW_THIN, "Mirror", 0, yco-=20, 120, 20, "");
|
||||
|
||||
uiDefBut(block, SEPR, 0, "", 0, yco-=6,
|
||||
menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Insert Key|I", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_KEY_INSERTKEY, "");
|
||||
|
||||
uiDefBut(block, SEPR, 0, "", 0, yco-=6,
|
||||
menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Duplicate|Shift D", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_KEY_DUPLICATE, "");
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Delete|X", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_KEY_DELETE, "");
|
||||
|
||||
uiDefBut(block, SEPR, 0, "", 0, yco-=6,
|
||||
menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Clean Action|O", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_KEY_CLEAN, "");
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Sample Keys|Alt O", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_KEY_SAMPLEKEYS, "");
|
||||
|
||||
uiDefBut(block, SEPR, 0, "", 0, yco-=6,
|
||||
menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
uiDefIconTextBlockBut(block, action_keymenu_handlemenu,
|
||||
NULL, ICON_RIGHTARROW_THIN,
|
||||
"Handle Type", 0, yco-=20, 120, 20, "");
|
||||
|
||||
uiDefBut(block, SEPR, 0, "", 0, yco-=6,
|
||||
menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
uiDefIconTextBlockBut(block, action_keymenu_extendmenu,
|
||||
NULL, ICON_RIGHTARROW_THIN,
|
||||
"Extend Mode", 0, yco-=20, 120, 20, "");
|
||||
uiDefIconTextBlockBut(block, action_keymenu_intpolmenu,
|
||||
NULL, ICON_RIGHTARROW_THIN,
|
||||
"Interpolation Mode", 0, yco-=20, 120, 20, "");
|
||||
|
||||
if(curarea->headertype==HEADERTOP) {
|
||||
uiBlockSetDirection(block, UI_DOWN);
|
||||
}
|
||||
else {
|
||||
uiBlockSetDirection(block, UI_TOP);
|
||||
uiBlockFlipOrder(block);
|
||||
}
|
||||
|
||||
uiTextBoundsBlock(block, 50);
|
||||
uiEndBlock(C, block);
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
/* Frame menu --------------------------- */
|
||||
|
||||
|
||||
// framemenu uses functions from keymenu
|
||||
static uiBlock *action_framemenu(bContext *C, ARegion *ar, void *arg_unused)
|
||||
{
|
||||
ScrArea *curarea= CTX_wm_area(C);
|
||||
uiBlock *block;
|
||||
short yco= 0, menuwidth=120;
|
||||
|
||||
block= uiBeginBlock(C, ar, "action_framemenu", UI_EMBOSSP);
|
||||
uiBlockSetButmFunc(block, do_action_keymenu, NULL);
|
||||
|
||||
uiDefIconTextBlockBut(block, action_keymenu_transformmenu,
|
||||
NULL, ICON_RIGHTARROW_THIN, "Transform", 0, yco-=20, 120, 20, "");
|
||||
|
||||
uiDefIconTextBlockBut(block, action_keymenu_snapmenu,
|
||||
NULL, ICON_RIGHTARROW_THIN, "Snap", 0, yco-=20, 120, 20, "");
|
||||
|
||||
uiDefIconTextBlockBut(block, action_keymenu_mirrormenu,
|
||||
NULL, ICON_RIGHTARROW_THIN, "Mirror", 0, yco-=20, 120, 20, "");
|
||||
|
||||
uiDefBut(block, SEPR, 0, "", 0, yco-=6,
|
||||
menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Duplicate|Shift D", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_KEY_DUPLICATE, "");
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Delete|X", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_KEY_DELETE, "");
|
||||
|
||||
if(curarea->headertype==HEADERTOP) {
|
||||
uiBlockSetDirection(block, UI_DOWN);
|
||||
}
|
||||
else {
|
||||
uiBlockSetDirection(block, UI_TOP);
|
||||
uiBlockFlipOrder(block);
|
||||
}
|
||||
|
||||
uiTextBoundsBlock(block, 50);
|
||||
uiEndBlock(C, block);
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
/* Marker menu --------------------------- */
|
||||
|
||||
static void do_markermenu(bContext *C, void *arg, int event)
|
||||
{
|
||||
switch(event)
|
||||
{
|
||||
case ACTMENU_MARKERS_ADD:
|
||||
//add_marker(CFRA);
|
||||
break;
|
||||
case ACTMENU_MARKERS_DUPLICATE:
|
||||
//duplicate_marker();
|
||||
break;
|
||||
case ACTMENU_MARKERS_DELETE:
|
||||
//remove_marker();
|
||||
break;
|
||||
case ACTMENU_MARKERS_NAME:
|
||||
//rename_marker();
|
||||
break;
|
||||
case ACTMENU_MARKERS_MOVE:
|
||||
//transform_markers('g', 0);
|
||||
break;
|
||||
case ACTMENU_MARKERS_LOCALADD:
|
||||
//action_add_localmarker(G.saction->action, CFRA);
|
||||
break;
|
||||
case ACTMENU_MARKERS_LOCALDELETE:
|
||||
//action_remove_localmarkers(G.saction->action);
|
||||
break;
|
||||
case ACTMENU_MARKERS_LOCALRENAME:
|
||||
//action_rename_localmarker(G.saction->action);
|
||||
break;
|
||||
case ACTMENU_MARKERS_LOCALMOVE:
|
||||
/*G.saction->flag |= SACTION_POSEMARKERS_MOVE;
|
||||
transform_markers('g', 0);
|
||||
G.saction->flag &= ~SACTION_POSEMARKERS_MOVE;*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uiBlock *action_markermenu(bContext *C, ARegion *ar, void *arg_unused)
|
||||
{
|
||||
SpaceAction *saction= (SpaceAction*)CTX_wm_space_data(C);
|
||||
ScrArea *curarea= CTX_wm_area(C);
|
||||
uiBlock *block;
|
||||
short yco= 0, menuwidth=120;
|
||||
|
||||
block= uiBeginBlock(C, ar, "action_markermenu", UI_EMBOSSP);
|
||||
uiBlockSetButmFunc(block, do_markermenu, NULL);
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Add Marker|M", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 1, ACTMENU_MARKERS_ADD, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Duplicate Marker|Ctrl Shift D", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 1, ACTMENU_MARKERS_DUPLICATE, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Delete Marker|Shift X", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 1, ACTMENU_MARKERS_DELETE, "");
|
||||
|
||||
uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "(Re)Name Marker|Ctrl M", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 1, ACTMENU_MARKERS_NAME, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Grab/Move Marker|Ctrl G", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 1, ACTMENU_MARKERS_MOVE, "");
|
||||
|
||||
if (saction->mode == SACTCONT_ACTION) {
|
||||
uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Add Pose Marker|Shift L", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 1, ACTMENU_MARKERS_LOCALADD, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Rename Pose Marker|Ctrl Shift L", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 1, ACTMENU_MARKERS_LOCALRENAME, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Delete Pose Marker|Alt L", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 1, ACTMENU_MARKERS_LOCALDELETE, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Grab/Move Pose Marker|Ctrl L", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 1, ACTMENU_MARKERS_LOCALMOVE, "");
|
||||
}
|
||||
|
||||
if(curarea->headertype==HEADERTOP) {
|
||||
uiBlockSetDirection(block, UI_DOWN);
|
||||
}
|
||||
else {
|
||||
uiBlockSetDirection(block, UI_TOP);
|
||||
uiBlockFlipOrder(block);
|
||||
}
|
||||
|
||||
uiTextBoundsBlock(block, 50);
|
||||
uiEndBlock(C, block);
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
|
||||
/* Channel menu --------------------------- */
|
||||
|
||||
static void do_channelmenu_posmenu(bContext *C, void *arg, int event)
|
||||
{
|
||||
switch(event)
|
||||
{
|
||||
case ACTMENU_CHANNELS_CHANPOS_MOVE_CHANNEL_DOWN:
|
||||
//rearrange_action_channels(REARRANGE_ACTCHAN_DOWN);
|
||||
break;
|
||||
case ACTMENU_CHANNELS_CHANPOS_MOVE_CHANNEL_UP:
|
||||
//rearrange_action_channels(REARRANGE_ACTCHAN_UP);
|
||||
break;
|
||||
case ACTMENU_CHANNELS_CHANPOS_MOVE_CHANNEL_TOP:
|
||||
//rearrange_action_channels(REARRANGE_ACTCHAN_TOP);
|
||||
break;
|
||||
case ACTMENU_CHANNELS_CHANPOS_MOVE_CHANNEL_BOTTOM:
|
||||
//rearrange_action_channels(REARRANGE_ACTCHAN_BOTTOM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uiBlock *action_channelmenu_posmenu(bContext *C, ARegion *ar, void *arg_unused)
|
||||
{
|
||||
uiBlock *block;
|
||||
short yco= 0, menuwidth=120;
|
||||
|
||||
block= uiBeginBlock(C, ar, "action_channelmenu_posmenu", UI_EMBOSSP);
|
||||
uiBlockSetButmFunc(block, do_channelmenu_posmenu, NULL);
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Move Up|Shift Page Up", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_CHANNELS_CHANPOS_MOVE_CHANNEL_UP, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Move Down|Shift Page Down", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_CHANNELS_CHANPOS_MOVE_CHANNEL_DOWN, "");
|
||||
|
||||
uiDefBut(block, SEPR, 0, "", 0, yco-=6,
|
||||
menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Move to Top|Ctrl Shift Page Up", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_CHANNELS_CHANPOS_MOVE_CHANNEL_TOP, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Move to Bottom|Ctrl Shift Page Down", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_CHANNELS_CHANPOS_MOVE_CHANNEL_BOTTOM, "");
|
||||
|
||||
uiBlockSetDirection(block, UI_RIGHT);
|
||||
uiTextBoundsBlock(block, 60);
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
static void do_channelmenu_groupmenu(bContext *C, void *arg, int event)
|
||||
{
|
||||
switch(event)
|
||||
{
|
||||
case ACTMENU_CHANNELS_GROUP_ADD_TOACTIVE:
|
||||
//action_groups_group(0);
|
||||
break;
|
||||
case ACTMENU_CHANNELS_GROUP_ADD_TONEW:
|
||||
//action_groups_group(1);
|
||||
break;
|
||||
case ACTMENU_CHANNELS_GROUP_REMOVE:
|
||||
//action_groups_ungroup();
|
||||
break;
|
||||
case ACTMENU_CHANNELS_GROUP_SYNCPOSE: /* Syncronise Pose-data and Action-data */
|
||||
//sync_pchan2achan_grouping();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uiBlock *action_channelmenu_groupmenu(bContext *C, ARegion *ar, void *arg_unused)
|
||||
{
|
||||
uiBlock *block;
|
||||
short yco= 0, menuwidth=120;
|
||||
|
||||
block= uiBeginBlock(C, ar, "action_channelmenu_groupmenu", UI_EMBOSSP);
|
||||
uiBlockSetButmFunc(block, do_channelmenu_groupmenu, NULL);
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Add to Active Group|Shift G", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_CHANNELS_GROUP_ADD_TOACTIVE, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Add to New Group|Ctrl Shift G", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_CHANNELS_GROUP_ADD_TONEW, "");
|
||||
|
||||
uiDefBut(block, SEPR, 0, "", 0, yco-=6,
|
||||
menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Remove From Group|Alt G", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_CHANNELS_GROUP_REMOVE, "");
|
||||
|
||||
uiDefBut(block, SEPR, 0, "", 0, yco-=6,
|
||||
menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Synchronise with Armature", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_CHANNELS_GROUP_SYNCPOSE, "");
|
||||
|
||||
uiBlockSetDirection(block, UI_RIGHT);
|
||||
uiTextBoundsBlock(block, 60);
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
static void do_channelmenu_settingsmenu(bContext *C, void *arg, int event)
|
||||
{
|
||||
//setflag_action_channels(event);
|
||||
}
|
||||
|
||||
static uiBlock *action_channelmenu_settingsmenu(bContext *C, ARegion *ar, void *arg_unused)
|
||||
{
|
||||
uiBlock *block;
|
||||
short yco= 0, menuwidth=120;
|
||||
|
||||
block= uiBeginBlock(C, ar, "action_channelmenu_settingsmenu", UI_EMBOSSP);
|
||||
uiBlockSetButmFunc(block, do_channelmenu_settingsmenu, NULL);
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Toggle a Setting|Shift W", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_CHANNELS_SETTINGS_TOGGLE, "");
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Enable a Setting|Ctrl Shift W", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_CHANNELS_SETTINGS_ENABLE, "");
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Disable a Setting|Alt W", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_CHANNELS_SETTINGS_DISABLE, "");
|
||||
|
||||
uiBlockSetDirection(block, UI_RIGHT);
|
||||
uiTextBoundsBlock(block, 60);
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
static void do_channelmenu(bContext *C, void *arg, int event)
|
||||
{
|
||||
SpaceAction *saction= (SpaceAction*)CTX_wm_space_data(C);
|
||||
|
||||
if (saction == NULL) return;
|
||||
|
||||
switch(event)
|
||||
{
|
||||
case ACTMENU_CHANNELS_OPENLEVELS: /* Unfold selected channels one step */
|
||||
//openclose_level_action(1);
|
||||
break;
|
||||
case ACTMENU_CHANNELS_CLOSELEVELS: /* Fold selected channels one step */
|
||||
//openclose_level_action(-1);
|
||||
break;
|
||||
case ACTMENU_CHANNELS_EXPANDALL: /* Expands all channels */
|
||||
//expand_all_action();
|
||||
break;
|
||||
case ACTMENU_CHANNELS_SHOWACHANS: /* Unfold groups that are hiding selected achans */
|
||||
//expand_obscuregroups_action();
|
||||
break;
|
||||
case ACTMENU_CHANNELS_DELETE: /* Deletes selected channels */
|
||||
//delete_action_channels();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uiBlock *action_channelmenu(bContext *C, ARegion *ar, void *arg_unused)
|
||||
{
|
||||
ScrArea *curarea= CTX_wm_area(C);
|
||||
uiBlock *block;
|
||||
short yco= 0, menuwidth=120;
|
||||
|
||||
block= uiBeginBlock(C, ar, "action_channelmenu", UI_EMBOSSP);
|
||||
uiBlockSetButmFunc(block, do_channelmenu, NULL);
|
||||
|
||||
uiDefIconTextBlockBut(block, action_channelmenu_groupmenu,
|
||||
NULL, ICON_RIGHTARROW_THIN,
|
||||
"Grouping", 0, yco-=20, 120, 20, "");
|
||||
|
||||
uiDefIconTextBlockBut(block, action_channelmenu_posmenu,
|
||||
NULL, ICON_RIGHTARROW_THIN,
|
||||
"Ordering", 0, yco-=20, 120, 20, "");
|
||||
|
||||
uiDefIconTextBlockBut(block, action_channelmenu_settingsmenu,
|
||||
NULL, ICON_RIGHTARROW_THIN,
|
||||
"Settings", 0, yco-=20, 120, 20, "");
|
||||
|
||||
uiDefBut(block, SEPR, 0, "", 0, yco-=6,
|
||||
menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Delete|X", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_CHANNELS_DELETE, "");
|
||||
|
||||
uiDefBut(block, SEPR, 0, "", 0, yco-=6,
|
||||
menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Toggle Show Hierachy|~", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_CHANNELS_EXPANDALL, "");
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Show Group-Hidden Channels|Shift ~", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_CHANNELS_SHOWACHANS, "");
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Expand One Level|Ctrl NumPad+", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_CHANNELS_OPENLEVELS, "");
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Collapse One Level|Ctrl NumPad-", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_CHANNELS_CLOSELEVELS, "");
|
||||
|
||||
if(curarea->headertype==HEADERTOP) {
|
||||
uiBlockSetDirection(block, UI_DOWN);
|
||||
}
|
||||
else {
|
||||
uiBlockSetDirection(block, UI_TOP);
|
||||
uiBlockFlipOrder(block);
|
||||
}
|
||||
|
||||
uiTextBoundsBlock(block, 50);
|
||||
uiEndBlock(C, block);
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
/* Grease Pencil --------------------------- */
|
||||
|
||||
/* Uses channelmenu functions */
|
||||
static uiBlock *action_gplayermenu(bContext *C, ARegion *ar, void *arg_unused)
|
||||
{
|
||||
ScrArea *curarea= CTX_wm_area(C);
|
||||
uiBlock *block;
|
||||
short yco= 0, menuwidth=120;
|
||||
|
||||
block= uiBeginBlock(C, ar, "action_gplayermenu", UI_EMBOSSP);
|
||||
uiBlockSetButmFunc(block, do_channelmenu, NULL);
|
||||
|
||||
uiDefIconTextBlockBut(block, action_channelmenu_settingsmenu,
|
||||
NULL, ICON_RIGHTARROW_THIN,
|
||||
"Settings", 0, yco-=20, 120, 20, "");
|
||||
|
||||
uiDefBut(block, SEPR, 0, "", 0, yco-=6,
|
||||
menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Delete|X", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_CHANNELS_DELETE, "");
|
||||
|
||||
if(curarea->headertype==HEADERTOP) {
|
||||
uiBlockSetDirection(block, UI_DOWN);
|
||||
}
|
||||
else {
|
||||
uiBlockSetDirection(block, UI_TOP);
|
||||
uiBlockFlipOrder(block);
|
||||
}
|
||||
|
||||
uiTextBoundsBlock(block, 50);
|
||||
uiEndBlock(C, block);
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
/* Select menu --------------------------- */
|
||||
|
||||
static void do_selectmenu_columnmenu(bContext *C, void *arg, int event)
|
||||
{
|
||||
switch (event) {
|
||||
case ACTMENU_SEL_COLUMN_MARKERSBETWEEN:
|
||||
//markers_selectkeys_between();
|
||||
break;
|
||||
case ACTMENU_SEL_COLUMN_KEYS:
|
||||
//column_select_action_keys(1);
|
||||
break;
|
||||
case ACTMENU_SEL_COLUMN_MARKERSCOLUMN:
|
||||
//column_select_action_keys(2);
|
||||
break;
|
||||
case ACTMENU_SEL_COLUMN_CFRA:
|
||||
//column_select_action_keys(3);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uiBlock *action_selectmenu_columnmenu(bContext *C, ARegion *ar, void *arg_unused)
|
||||
{
|
||||
SpaceAction *saction= (SpaceAction*)CTX_wm_space_data(C);
|
||||
uiBlock *block;
|
||||
short yco= 0, menuwidth=120;
|
||||
|
||||
block= uiBeginBlock(C, ar, "action_selectmenu_columnmenu", UI_EMBOSSP);
|
||||
uiBlockSetButmFunc(block, do_selectmenu_columnmenu, NULL);
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"On Selected Keys|K", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_SEL_COLUMN_KEYS, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"On Current Frame|Ctrl K", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_SEL_COLUMN_CFRA, "");
|
||||
|
||||
if (SACTION_HASMARKERS) {
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"On Selected Markers|Shift K", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_SEL_COLUMN_MARKERSCOLUMN, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Between Selected Markers|Alt K", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_SEL_COLUMN_MARKERSBETWEEN, "");
|
||||
}
|
||||
|
||||
uiBlockSetDirection(block, UI_RIGHT);
|
||||
uiTextBoundsBlock(block, 60);
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
static void do_selectmenu(bContext *C, void *arg, int event)
|
||||
{
|
||||
SpaceAction *saction= (SpaceAction*)CTX_wm_space_data(C);
|
||||
//Key *key;
|
||||
|
||||
if (saction == NULL) return;
|
||||
|
||||
//key = get_action_mesh_key();
|
||||
|
||||
switch(event)
|
||||
{
|
||||
case ACTMENU_SEL_BORDER: /* Border Select */
|
||||
//borderselect_action();
|
||||
break;
|
||||
|
||||
case ACTMENU_SEL_BORDERC: /* Border Select */
|
||||
//borderselect_actionchannels();
|
||||
break;
|
||||
|
||||
case ACTMENU_SEL_BORDERM: /* Border Select */
|
||||
//borderselect_markers();
|
||||
break;
|
||||
|
||||
case ACTMENU_SEL_ALL_KEYS: /* Select/Deselect All Keys */
|
||||
/*deselect_action_keys(1, 1);
|
||||
BIF_undo_push("(De)Select Keys");
|
||||
allqueue(REDRAWACTION, 0);
|
||||
allqueue(REDRAWNLA, 0);
|
||||
allqueue(REDRAWIPO, 0);*/
|
||||
break;
|
||||
|
||||
case ACTMENU_SEL_ALL_CHAN: /* Select/Deselect All Channels */
|
||||
/*deselect_action_channels(1);
|
||||
BIF_undo_push("(De)Select Action Channels");
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
allqueue(REDRAWACTION, 0);
|
||||
allqueue(REDRAWNLA, 0);
|
||||
allqueue(REDRAWIPO, 0);*/
|
||||
break;
|
||||
|
||||
case ACTMENU_SEL_ALL_MARKERS: /* select/deselect all markers */
|
||||
/*deselect_markers(1, 0);
|
||||
BIF_undo_push("(De)Select Markers");
|
||||
allqueue(REDRAWMARKER, 0);*/
|
||||
break;
|
||||
|
||||
case ACTMENU_SEL_INVERSE_KEYS: /* invert selection status of keys */
|
||||
/*deselect_action_keys(0, 2);
|
||||
BIF_undo_push("Inverse Keys");
|
||||
allqueue(REDRAWACTION, 0);
|
||||
allqueue(REDRAWNLA, 0);
|
||||
allqueue(REDRAWIPO, 0);*/
|
||||
break;
|
||||
|
||||
case ACTMENU_SEL_INVERSE_CHANNELS: /* invert selection status of channels */
|
||||
/*deselect_action_channels(2);
|
||||
BIF_undo_push("Inverse Action Channels");
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
allqueue(REDRAWACTION, 0);
|
||||
allqueue(REDRAWNLA, 0);
|
||||
allqueue(REDRAWIPO, 0);*/
|
||||
break;
|
||||
|
||||
case ACTMENU_SEL_INVERSE_MARKERS: /* invert selection of markers */
|
||||
/*deselect_markers(0, 2);
|
||||
BIF_undo_push("Inverse Action Channels");
|
||||
allqueue(REDRAWMARKER, 0);*/
|
||||
break;
|
||||
|
||||
case ACTMENU_SEL_LEFTKEYS:
|
||||
//selectkeys_leftright(1, SELECT_REPLACE);
|
||||
break;
|
||||
|
||||
case ACTMENU_SEL_RIGHTKEYS:
|
||||
//selectkeys_leftright(0, SELECT_REPLACE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uiBlock *action_selectmenu(bContext *C, ARegion *ar, void *arg_unused)
|
||||
{
|
||||
ScrArea *curarea= CTX_wm_area(C);
|
||||
SpaceAction *saction= (SpaceAction*)CTX_wm_space_data(C);
|
||||
uiBlock *block;
|
||||
short yco= 0, menuwidth=120;
|
||||
|
||||
block= uiBeginBlock(C, ar, "action_selectmenu", UI_EMBOSSP);
|
||||
uiBlockSetButmFunc(block, do_selectmenu, NULL);
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Border Select Keys|B", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_SEL_BORDER, "");
|
||||
if (SACTION_HASMARKERS) {
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Border Select Markers|Ctrl B", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_SEL_BORDERM, "");
|
||||
}
|
||||
if (saction->mode != SACTCONT_SHAPEKEY) {
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Border Select Channels|B", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_SEL_BORDERC, "");
|
||||
}
|
||||
|
||||
uiDefBut(block, SEPR, 0, "", 0, yco-=6,
|
||||
menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Select/Deselect All Keys|A", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_SEL_ALL_KEYS, "");
|
||||
if (SACTION_HASMARKERS) {
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Select/Deselect All Markers|Ctrl A", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_SEL_ALL_MARKERS, "");
|
||||
}
|
||||
if (saction->mode != SACTCONT_SHAPEKEY) {
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Select/Deselect All Channels|A", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_SEL_ALL_CHAN, "");
|
||||
}
|
||||
|
||||
uiDefBut(block, SEPR, 0, "", 0, yco-=6,
|
||||
menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Inverse Keys|Ctrl I", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_SEL_INVERSE_KEYS, "");
|
||||
if (SACTION_HASMARKERS) {
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Inverse Markers|Ctrl Shift I", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_SEL_INVERSE_MARKERS, "");
|
||||
}
|
||||
if (saction->mode != SACTCONT_SHAPEKEY) {
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Inverse All Channels|Ctrl I", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_SEL_INVERSE_CHANNELS, "");
|
||||
}
|
||||
|
||||
uiDefBut(block, SEPR, 0, "", 0, yco-=6,
|
||||
menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Back In Time|Alt RMB", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_SEL_LEFTKEYS, "");
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Ahead In Time|Alt RMB", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_SEL_RIGHTKEYS, "");
|
||||
|
||||
uiDefBut(block, SEPR, 0, "", 0, yco-=6,
|
||||
menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
uiDefIconTextBlockBut(block, action_selectmenu_columnmenu,
|
||||
NULL, ICON_RIGHTARROW_THIN, "Column Select Keys", 0, yco-=20, 120, 20, "");
|
||||
|
||||
if(curarea->headertype==HEADERTOP) {
|
||||
uiBlockSetDirection(block, UI_DOWN);
|
||||
}
|
||||
else {
|
||||
uiBlockSetDirection(block, UI_TOP);
|
||||
uiBlockFlipOrder(block);
|
||||
}
|
||||
|
||||
uiTextBoundsBlock(block, 50);
|
||||
uiEndBlock(C, block);
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
/* View menu --------------------------- */
|
||||
|
||||
static void do_viewmenu(bContext *C, void *arg, int event)
|
||||
{
|
||||
switch(event) {
|
||||
case ACTMENU_VIEW_CENTERVIEW: /* Center View to Current Frame */
|
||||
//center_currframe();
|
||||
break;
|
||||
case ACTMENU_VIEW_AUTOUPDATE: /* Update Automatically */
|
||||
/*if (BTST(G.saction->lock, 0))
|
||||
G.saction->lock = BCLR(G.saction->lock, 0);
|
||||
else
|
||||
G.saction->lock = BSET(G.saction->lock, 0);*/
|
||||
break;
|
||||
case ACTMENU_VIEW_PLAY3D: /* Play Back Animation */
|
||||
//play_anim(0);
|
||||
break;
|
||||
case ACTMENU_VIEW_PLAYALL: /* Play Back Animation in All */
|
||||
//play_anim(1);
|
||||
break;
|
||||
case ACTMENU_VIEW_ALL: /* View All */
|
||||
//do_action_buttons(B_ACTHOME);
|
||||
break;
|
||||
case ACTMENU_VIEW_LOCK:
|
||||
/*G.v2d->flag ^= V2D_VIEWLOCK;
|
||||
if (G.v2d->flag & V2D_VIEWLOCK)
|
||||
view2d_do_locks(curarea, 0);*/
|
||||
break;
|
||||
case ACTMENU_VIEW_SLIDERS: /* Show sliders (when applicable) */
|
||||
//G.saction->flag ^= SACTION_SLIDERS;
|
||||
break;
|
||||
case ACTMENU_VIEW_MAXIMIZE: /* Maximize Window */
|
||||
/* using event B_FULL */
|
||||
break;
|
||||
case ACTMENU_VIEW_NEXTMARKER: /* Jump to next marker */
|
||||
//nextprev_marker(1);
|
||||
break;
|
||||
case ACTMENU_VIEW_PREVMARKER: /* Jump to previous marker */
|
||||
//nextprev_marker(-1);
|
||||
break;
|
||||
case ACTMENU_VIEW_TIME: /* switch between frames and seconds display */
|
||||
//G.saction->flag ^= SACTION_DRAWTIME;
|
||||
break;
|
||||
case ACTMENU_VIEW_NOHIDE: /* Show hidden channels */
|
||||
//G.saction->flag ^= SACTION_NOHIDE;
|
||||
break;
|
||||
case ACTMENU_VIEW_NEXTKEYFRAME: /* Jump to next keyframe */
|
||||
//nextprev_action_keyframe(1);
|
||||
break;
|
||||
case ACTMENU_VIEW_PREVKEYFRAME: /* Jump to previous keyframe */
|
||||
//nextprev_action_keyframe(-1);
|
||||
break;
|
||||
case ACTMENU_VIEW_TRANSDELDUPS: /* Don't delete duplicate/overlapping keyframes after transform */
|
||||
//G.saction->flag ^= SACTION_NOTRANSKEYCULL;
|
||||
break;
|
||||
case ACTMENU_VIEW_HORIZOPTIMISE: /* Include keyframes not in view (horizontally) when preparing to draw */
|
||||
//G.saction->flag ^= SACTION_HORIZOPTIMISEON;
|
||||
break;
|
||||
case ACTMENU_VIEW_GCOLORS: /* Draw grouped-action channels using its group's color */
|
||||
//G.saction->flag ^= SACTION_NODRAWGCOLORS;
|
||||
break;
|
||||
case ACTMENU_VIEW_PREVRANGESET: /* Set preview range */
|
||||
//anim_previewrange_set();
|
||||
break;
|
||||
case ACTMENU_VIEW_PREVRANGECLEAR: /* Clear preview range */
|
||||
//anim_previewrange_clear();
|
||||
break;
|
||||
case ACTMENU_VIEW_PREVRANGEAUTO: /* Auto preview-range length */
|
||||
//action_previewrange_set(G.saction->action);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uiBlock *action_viewmenu(bContext *C, ARegion *ar, void *arg_unused)
|
||||
{
|
||||
ScrArea *curarea= CTX_wm_area(C);
|
||||
SpaceAction *saction= (SpaceAction*)CTX_wm_space_data(C);
|
||||
View2D *v2d= UI_view2d_fromcontext_rwin(C);
|
||||
uiBlock *block;
|
||||
short yco= 0, menuwidth=120;
|
||||
|
||||
block= uiBeginBlock(C, ar, "viewmenu", UI_EMBOSSP);
|
||||
uiBlockSetButmFunc(block, do_viewmenu, NULL);
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Center View to Current Frame|C", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 1,
|
||||
ACTMENU_VIEW_CENTERVIEW, "");
|
||||
|
||||
uiDefBut(block, SEPR, 0, "", 0, yco-=6,
|
||||
menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
if (saction->flag & SACTION_DRAWTIME) {
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Show Frames|Ctrl T", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 1,
|
||||
ACTMENU_VIEW_TIME, "");
|
||||
}
|
||||
else {
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Show Seconds|Ctrl T", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 1,
|
||||
ACTMENU_VIEW_TIME, "");
|
||||
}
|
||||
|
||||
uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
if (saction->mode == SACTCONT_GPENCIL) {
|
||||
// this option may get removed in future
|
||||
uiDefIconTextBut(block, BUTM, 1, (saction->flag & SACTION_HORIZOPTIMISEON)?ICON_CHECKBOX_HLT:ICON_CHECKBOX_DEHLT,
|
||||
"Cull Out-of-View Keys (Time)|", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 1,
|
||||
ACTMENU_VIEW_HORIZOPTIMISE, "");
|
||||
}
|
||||
else {
|
||||
uiDefIconTextBut(block, BUTM, 1, (saction->flag & SACTION_SLIDERS)?ICON_CHECKBOX_HLT:ICON_CHECKBOX_DEHLT,
|
||||
"Show Sliders|", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 1,
|
||||
ACTMENU_VIEW_SLIDERS, "");
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, (saction->flag & SACTION_NOHIDE)?ICON_CHECKBOX_HLT:ICON_CHECKBOX_DEHLT,
|
||||
"Show Hidden Channels|", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 1,
|
||||
ACTMENU_VIEW_NOHIDE, "");
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, (saction->flag & SACTION_NODRAWGCOLORS)?ICON_CHECKBOX_DEHLT:ICON_CHECKBOX_HLT,
|
||||
"Use Group Colors|", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 1,
|
||||
ACTMENU_VIEW_GCOLORS, "");
|
||||
|
||||
// this option may get removed in future
|
||||
uiDefIconTextBut(block, BUTM, 1, (saction->flag & SACTION_HORIZOPTIMISEON)?ICON_CHECKBOX_HLT:ICON_CHECKBOX_DEHLT,
|
||||
"Cull Out-of-View Keys (Time)|", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 1,
|
||||
ACTMENU_VIEW_HORIZOPTIMISE, "");
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, (saction->flag & SACTION_NOTRANSKEYCULL)?ICON_CHECKBOX_DEHLT:ICON_CHECKBOX_HLT,
|
||||
"AutoMerge Keyframes|", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 1,
|
||||
ACTMENU_VIEW_TRANSDELDUPS, "");
|
||||
}
|
||||
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, (v2d->flag & V2D_VIEWSYNC_SCREEN_TIME)?ICON_CHECKBOX_HLT:ICON_CHECKBOX_DEHLT,
|
||||
"Lock Time to Other Windows|", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 1,
|
||||
ACTMENU_VIEW_LOCK, "");
|
||||
|
||||
/*uiDefIconTextBut(block, BUTM, 1, BTST(saction->lock, 0)?ICON_CHECKBOX_HLT:ICON_CHECKBOX_DEHLT,
|
||||
"Update Automatically|", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 1,
|
||||
ACTMENU_VIEW_AUTOUPDATE, "");*/
|
||||
|
||||
uiDefBut(block, SEPR, 0, "", 0, yco-=6,
|
||||
menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Jump To Next Marker|PageUp", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_VIEW_NEXTMARKER, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Jump To Prev Marker|PageDown", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_VIEW_PREVMARKER, "");
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Jump To Next Keyframe|Ctrl PageUp", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_VIEW_NEXTKEYFRAME, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Jump To Prev Keyframe|Ctrl PageDown", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_VIEW_PREVKEYFRAME, "");
|
||||
|
||||
uiDefBut(block, SEPR, 0, "", 0, yco-=6,
|
||||
menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Play Back Animation|Alt A", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 1,
|
||||
ACTMENU_VIEW_PLAY3D, "");
|
||||
//uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
// "Play Back Animation in 3D View|Alt Shift A", 0, yco-=20,
|
||||
// menuwidth, 19, NULL, 0.0, 0.0, 1,
|
||||
// ACTMENU_VIEW_PLAYALL, "");
|
||||
|
||||
uiDefBut(block, SEPR, 0, "", 0, yco-=6,
|
||||
menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Set Preview Range|Ctrl P", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 1,
|
||||
ACTMENU_VIEW_PREVRANGESET, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Clear Preview Range|Alt P", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 1,
|
||||
ACTMENU_VIEW_PREVRANGECLEAR, "");
|
||||
|
||||
if ((saction->mode == SACTCONT_ACTION) && (saction->action)) {
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Preview Range from Action Length|Ctrl Alt P", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 1,
|
||||
ACTMENU_VIEW_PREVRANGEAUTO, "");
|
||||
}
|
||||
|
||||
uiDefBut(block, SEPR, 0, "", 0, yco-=6,
|
||||
menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"View All|Home", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 1,
|
||||
ACTMENU_VIEW_ALL, "");
|
||||
|
||||
/* if (!curarea->full)
|
||||
uiDefIconTextBut(block, BUTM, B_FULL, ICON_BLANK1,
|
||||
"Maximize Window|Ctrl UpArrow", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_VIEW_MAXIMIZE, "");
|
||||
if (sa->full)
|
||||
uiItemO(layout, NULL, 0, "SCREEN_OT_screen_full_area"); // "Tile Window", Ctrl UpArrow
|
||||
else
|
||||
uiDefIconTextBut(block, BUTM, B_FULL, ICON_BLANK1,
|
||||
"Tile Window|Ctrl DownArrow", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 0,
|
||||
ACTMENU_VIEW_MAXIMIZE, "");
|
||||
*/
|
||||
uiItemO(layout, NULL, 0, "SCREEN_OT_screen_full_area"); // "Maximize Window", Ctrl DownArrow
|
||||
}
|
||||
|
||||
static void act_selectmenu(bContext *C, uiLayout *layout, void *arg_unused)
|
||||
{
|
||||
uiItemO(layout, NULL, 0, "ACT_OT_select_all_toggle");
|
||||
uiItemBooleanO(layout, "Invert All", 0, "ACT_OT_select_all_toggle", "invert", 1);
|
||||
|
||||
if (curarea->headertype==HEADERTOP) {
|
||||
uiBlockSetDirection(block, UI_DOWN);
|
||||
}
|
||||
else {
|
||||
uiBlockSetDirection(block, UI_TOP);
|
||||
uiBlockFlipOrder(block);
|
||||
}
|
||||
uiItemS(layout);
|
||||
|
||||
uiTextBoundsBlock(block, 50);
|
||||
uiEndBlock(C, block);
|
||||
uiItemO(layout, NULL, 0, "ACT_OT_select_border");
|
||||
uiItemBooleanO(layout, "Border Axis Range", 0, "ACT_OT_select_border", "axis_range", 1);
|
||||
|
||||
return block;
|
||||
uiItemS(layout);
|
||||
|
||||
uiItemEnumO(layout, "Columns on Selected Keys", 0, "ACT_OT_select_column", "mode", ACTKEYS_COLUMNSEL_KEYS);
|
||||
uiItemEnumO(layout, "Column on Current Frame", 0, "ACT_OT_select_column", "mode", ACTKEYS_COLUMNSEL_CFRA);
|
||||
|
||||
uiItemEnumO(layout, "Columns on Selected Markers", 0, "ACT_OT_select_column", "mode", ACTKEYS_COLUMNSEL_MARKERS_COLUMN);
|
||||
uiItemEnumO(layout, "Between Selected Markers", 0, "ACT_OT_select_column", "mode", ACTKEYS_COLUMNSEL_MARKERS_BETWEEN);
|
||||
}
|
||||
|
||||
static void act_channelmenu(bContext *C, uiLayout *layout, void *arg_unused)
|
||||
{
|
||||
uiItemO(layout, NULL, 0, "ANIM_OT_channels_setting_toggle");
|
||||
uiItemO(layout, NULL, 0, "ANIM_OT_channels_setting_enable");
|
||||
uiItemO(layout, NULL, 0, "ANIM_OT_channels_setting_disable");
|
||||
|
||||
uiItemS(layout);
|
||||
|
||||
uiItemO(layout, NULL, 0, "ANIM_OT_channels_editable_toggle");
|
||||
|
||||
uiItemS(layout);
|
||||
|
||||
uiItemO(layout, NULL, 0, "ANIM_OT_channels_expand");
|
||||
uiItemO(layout, NULL, 0, "ANIM_OT_channels_collapse");
|
||||
}
|
||||
|
||||
static void act_gplayermenu(bContext *C, uiLayout *layout, void *arg_unused)
|
||||
{
|
||||
//uiItemMenuF(layout, "Transform", 0, nla_edit_transformmenu);
|
||||
//uiItemS(layout);
|
||||
//uiItemO(layout, NULL, 0, "NLAEDIT_OT_duplicate");
|
||||
}
|
||||
|
||||
static void act_edit_transformmenu(bContext *C, uiLayout *layout, void *arg_unused)
|
||||
{
|
||||
uiItemEnumO(layout, "Grab/Move", 0, "TFM_OT_transform", "mode", TFM_TIME_TRANSLATE);
|
||||
uiItemEnumO(layout, "Extend", 0, "TFM_OT_transform", "mode", TFM_TIME_EXTEND);
|
||||
uiItemEnumO(layout, "Scale", 0, "TFM_OT_transform", "mode", TFM_TIME_SCALE);
|
||||
}
|
||||
|
||||
static void act_edit_snapmenu(bContext *C, uiLayout *layout, void *arg_unused)
|
||||
{
|
||||
uiItemEnumO(layout, NULL, 0, "ACT_OT_snap", "type", ACTKEYS_SNAP_CFRA);
|
||||
uiItemEnumO(layout, NULL, 0, "ACT_OT_snap", "type", ACTKEYS_SNAP_NEAREST_FRAME);
|
||||
uiItemEnumO(layout, NULL, 0, "ACT_OT_snap", "type", ACTKEYS_SNAP_NEAREST_SECOND);
|
||||
uiItemEnumO(layout, NULL, 0, "ACT_OT_snap", "type", ACTKEYS_SNAP_NEAREST_MARKER);
|
||||
}
|
||||
|
||||
static void act_edit_mirrormenu(bContext *C, uiLayout *layout, void *arg_unused)
|
||||
{
|
||||
uiItemEnumO(layout, NULL, 0, "ACT_OT_mirror", "type", ACTKEYS_MIRROR_CFRA);
|
||||
uiItemEnumO(layout, NULL, 0, "ACT_OT_mirror", "type", ACTKEYS_MIRROR_YAXIS);
|
||||
uiItemEnumO(layout, NULL, 0, "ACT_OT_mirror", "type", ACTKEYS_MIRROR_XAXIS);
|
||||
uiItemEnumO(layout, NULL, 0, "ACT_OT_mirror", "type", ACTKEYS_MIRROR_MARKER);
|
||||
}
|
||||
|
||||
static void act_edit_handlesmenu(bContext *C, uiLayout *layout, void *arg_unused)
|
||||
{
|
||||
uiItemEnumO(layout, NULL, 0, "ACT_OT_handle_type", "type", HD_FREE);
|
||||
uiItemEnumO(layout, NULL, 0, "ACT_OT_handle_type", "type", HD_AUTO);
|
||||
uiItemEnumO(layout, NULL, 0, "ACT_OT_handle_type", "type", HD_VECT);
|
||||
uiItemEnumO(layout, NULL, 0, "ACT_OT_handle_type", "type", HD_ALIGN);
|
||||
uiItemEnumO(layout, NULL, 0, "ACT_OT_handle_type", "type", HD_AUTO_ANIM); // xxx?
|
||||
}
|
||||
|
||||
static void act_edit_ipomenu(bContext *C, uiLayout *layout, void *arg_unused)
|
||||
{
|
||||
uiItemEnumO(layout, NULL, 0, "ACT_OT_interpolation_type", "type", BEZT_IPO_CONST);
|
||||
uiItemEnumO(layout, NULL, 0, "ACT_OT_interpolation_type", "type", BEZT_IPO_LIN);
|
||||
uiItemEnumO(layout, NULL, 0, "ACT_OT_interpolation_type", "type", BEZT_IPO_BEZ);
|
||||
}
|
||||
|
||||
static void act_edit_expomenu(bContext *C, uiLayout *layout, void *arg_unused)
|
||||
{
|
||||
uiItemEnumO(layout, NULL, 0, "ACT_OT_extrapolation_type", "type", FCURVE_EXTRAPOLATE_CONSTANT);
|
||||
uiItemEnumO(layout, NULL, 0, "ACT_OT_extrapolation_type", "type", FCURVE_EXTRAPOLATE_LINEAR);
|
||||
}
|
||||
|
||||
static void act_editmenu(bContext *C, uiLayout *layout, void *arg_unused)
|
||||
{
|
||||
uiItemMenuF(layout, "Transform", 0, act_edit_transformmenu);
|
||||
uiItemMenuF(layout, "Snap", 0, act_edit_snapmenu);
|
||||
uiItemMenuF(layout, "Mirror", 0, act_edit_mirrormenu);
|
||||
|
||||
uiItemS(layout);
|
||||
|
||||
uiItemO(layout, NULL, 0, "ACT_OT_insert_keyframe");
|
||||
|
||||
uiItemS(layout);
|
||||
|
||||
uiItemO(layout, NULL, 0, "ACT_OT_duplicate");
|
||||
uiItemO(layout, NULL, 0, "ACT_OT_delete");
|
||||
|
||||
uiItemS(layout);
|
||||
|
||||
uiItemMenuF(layout, "Handle Type", 0, act_edit_handlesmenu);
|
||||
uiItemMenuF(layout, "Interpolation Mode", 0, act_edit_ipomenu);
|
||||
uiItemMenuF(layout, "Extrapolation Mode", 0, act_edit_expomenu);
|
||||
|
||||
uiItemS(layout);
|
||||
|
||||
uiItemO(layout, NULL, 0, "ACT_OT_clean");
|
||||
uiItemO(layout, NULL, 0, "ACT_OT_sample");
|
||||
|
||||
uiItemS(layout);
|
||||
|
||||
uiItemO(layout, NULL, 0, "ACT_OT_copy");
|
||||
uiItemO(layout, NULL, 0, "ACT_OT_paste");
|
||||
}
|
||||
|
||||
/* ************************ header area region *********************** */
|
||||
|
||||
static void do_action_buttons(bContext *C, void *arg, int event)
|
||||
{
|
||||
switch(event) {
|
||||
switch (event) {
|
||||
case B_REDR:
|
||||
ED_area_tag_redraw(CTX_wm_area(C));
|
||||
break;
|
||||
|
||||
case B_ACTCOPYKEYS:
|
||||
WM_operator_name_call(C, "ACT_OT_keyframes_copy", WM_OP_EXEC_REGION_WIN, NULL);
|
||||
break;
|
||||
case B_ACTPASTEKEYS:
|
||||
WM_operator_name_call(C, "ACT_OT_keyframes_paste", WM_OP_EXEC_REGION_WIN, NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1622,45 +314,38 @@ void action_header_buttons(const bContext *C, ARegion *ar)
|
||||
if ((sa->flag & HEADER_NO_PULLDOWN)==0) {
|
||||
|
||||
xmax= GetButStringLength("View");
|
||||
uiDefPulldownBut(block, action_viewmenu, CTX_wm_area(C),
|
||||
"View", xco, yco-2, xmax-3, 24, "");
|
||||
uiDefMenuBut(block, act_viewmenu, NULL, "View", xco, yco, xmax-3, 20, "");
|
||||
xco+= xmax;
|
||||
|
||||
xmax= GetButStringLength("Select");
|
||||
uiDefPulldownBut(block, action_selectmenu, CTX_wm_area(C),
|
||||
"Select", xco, yco-2, xmax-3, 24, "");
|
||||
uiDefMenuBut(block, act_selectmenu, NULL, "Select", xco, yco, xmax-3, 20, "");
|
||||
xco+= xmax;
|
||||
|
||||
if ( (saction->mode == SACTCONT_DOPESHEET) ||
|
||||
((saction->action) && (saction->mode==SACTCONT_ACTION)) )
|
||||
{
|
||||
xmax= GetButStringLength("Channel");
|
||||
uiDefPulldownBut(block, action_channelmenu, CTX_wm_area(C),
|
||||
"Channel", xco, yco-2, xmax-3, 24, "");
|
||||
uiDefMenuBut(block, act_channelmenu, NULL, "Channel", xco, yco, xmax-3, 20, "");
|
||||
xco+= xmax;
|
||||
}
|
||||
else if (saction->mode==SACTCONT_GPENCIL) {
|
||||
xmax= GetButStringLength("Channel");
|
||||
uiDefPulldownBut(block, action_gplayermenu, CTX_wm_area(C),
|
||||
"Channel", xco, yco-2, xmax-3, 24, "");
|
||||
uiDefMenuBut(block, act_gplayermenu, NULL, "Channel", xco, yco, xmax-3, 20, "");
|
||||
xco+= xmax;
|
||||
}
|
||||
|
||||
xmax= GetButStringLength("Marker");
|
||||
uiDefPulldownBut(block, action_markermenu, CTX_wm_area(C),
|
||||
"Marker", xco, yco-2, xmax-3, 24, "");
|
||||
xco+= xmax;
|
||||
//xmax= GetButStringLength("Marker");
|
||||
//uiDefMenuBut(block, act_markermenu, NULL, "Marker", xco, yco, xmax-3, 20, "");
|
||||
//xco+= xmax;
|
||||
|
||||
if (saction->mode == SACTCONT_GPENCIL) {
|
||||
xmax= GetButStringLength("Frame");
|
||||
uiDefPulldownBut(block, action_framemenu, CTX_wm_area(C),
|
||||
"Frame", xco, yco-2, xmax-3, 24, "");
|
||||
xco+= xmax;
|
||||
//xmax= GetButStringLength("Frame");
|
||||
//uiDefMenuBut(block, act_selectmenu, NULL, "Frame", xco, yco, xmax-3, 20, "");
|
||||
//xco+= xmax;
|
||||
}
|
||||
else {
|
||||
xmax= GetButStringLength("Key");
|
||||
uiDefPulldownBut(block, action_keymenu, CTX_wm_area(C),
|
||||
"Key", xco, yco-2, xmax-3, 24, "");
|
||||
uiDefMenuBut(block, act_editmenu, NULL, "Key", xco, yco, xmax-3, 20, "");
|
||||
xco+= xmax;
|
||||
}
|
||||
}
|
||||
@@ -1712,8 +397,9 @@ void action_header_buttons(const bContext *C, ARegion *ar)
|
||||
|
||||
/* COPY PASTE */
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefIconBut(block, BUT, B_ACTCOPYKEYS, ICON_COPYDOWN, xco,yco,XIC,YIC, 0, 0, 0, 0, 0, "Copies the selected keyframes from the selected channel(s) to the buffer");
|
||||
uiDefIconBut(block, BUT, B_ACTPASTEKEYS, ICON_PASTEDOWN, xco+=XIC,yco,XIC,YIC, 0, 0, 0, 0, 0, "Pastes the keyframes from the buffer");
|
||||
uiDefIconButO(block, BUT, "ACT_OT_copy", WM_OP_INVOKE_REGION_WIN, ICON_COPYDOWN, xco,yco,XIC,YIC, "Copies the selected keyframes to the buffer.");
|
||||
xco += XIC;
|
||||
uiDefIconButO(block, BUT, "ACT_OT_paste", WM_OP_INVOKE_REGION_WIN, ICON_PASTEDOWN, xco,yco,XIC,YIC, "Pastes the keyframes from the buffer into the selected channels.");
|
||||
uiBlockEndAlign(block);
|
||||
xco += (XIC + 8);
|
||||
|
||||
|
||||
@@ -53,10 +53,10 @@ void action_header_buttons(const struct bContext *C, struct ARegion *ar);
|
||||
/* ***************************************** */
|
||||
/* action_select.c */
|
||||
|
||||
void ACT_OT_keyframes_select_all_toggle(struct wmOperatorType *ot);
|
||||
void ACT_OT_keyframes_select_border(struct wmOperatorType *ot);
|
||||
void ACT_OT_keyframes_select_column(struct wmOperatorType *ot);
|
||||
void ACT_OT_keyframes_clickselect(struct wmOperatorType *ot);
|
||||
void ACT_OT_select_all_toggle(struct wmOperatorType *ot);
|
||||
void ACT_OT_select_border(struct wmOperatorType *ot);
|
||||
void ACT_OT_select_column(struct wmOperatorType *ot);
|
||||
void ACT_OT_clickselect(struct wmOperatorType *ot);
|
||||
|
||||
/* defines for left-right select tool */
|
||||
enum {
|
||||
@@ -80,22 +80,23 @@ enum {
|
||||
void ACT_OT_previewrange_set(struct wmOperatorType *ot);
|
||||
void ACT_OT_view_all(struct wmOperatorType *ot);
|
||||
|
||||
void ACT_OT_keyframes_copy(struct wmOperatorType *ot);
|
||||
void ACT_OT_keyframes_paste(struct wmOperatorType *ot);
|
||||
void ACT_OT_copy(struct wmOperatorType *ot);
|
||||
void ACT_OT_paste(struct wmOperatorType *ot);
|
||||
|
||||
void ACT_OT_keyframes_insert(struct wmOperatorType *ot);
|
||||
void ACT_OT_keyframes_duplicate(struct wmOperatorType *ot);
|
||||
void ACT_OT_keyframes_delete(struct wmOperatorType *ot);
|
||||
void ACT_OT_keyframes_clean(struct wmOperatorType *ot);
|
||||
void ACT_OT_keyframes_sample(struct wmOperatorType *ot);
|
||||
void ACT_OT_insert_keyframe(struct wmOperatorType *ot);
|
||||
void ACT_OT_duplicate(struct wmOperatorType *ot);
|
||||
void ACT_OT_delete(struct wmOperatorType *ot);
|
||||
void ACT_OT_clean(struct wmOperatorType *ot);
|
||||
void ACT_OT_sample(struct wmOperatorType *ot);
|
||||
|
||||
void ACT_OT_keyframes_handle_type_set(struct wmOperatorType *ot);
|
||||
void ACT_OT_keyframes_interpolation_type(struct wmOperatorType *ot);
|
||||
void ACT_OT_keyframes_extrapolation_type_set(struct wmOperatorType *ot);
|
||||
void ACT_OT_handle_type(struct wmOperatorType *ot);
|
||||
void ACT_OT_interpolation_type(struct wmOperatorType *ot);
|
||||
void ACT_OT_extrapolation_type(struct wmOperatorType *ot);
|
||||
|
||||
void ACT_OT_keyframes_cfrasnap(struct wmOperatorType *ot);
|
||||
void ACT_OT_keyframes_snap(struct wmOperatorType *ot);
|
||||
void ACT_OT_keyframes_mirror(struct wmOperatorType *ot);
|
||||
void ACT_OT_frame_jump(struct wmOperatorType *ot);
|
||||
|
||||
void ACT_OT_snap(struct wmOperatorType *ot);
|
||||
void ACT_OT_mirror(struct wmOperatorType *ot);
|
||||
|
||||
/* defines for snap keyframes
|
||||
* NOTE: keep in sync with eEditKeyframes_Snap (in ED_keyframes_edit.h)
|
||||
|
||||
@@ -63,25 +63,25 @@ void action_operatortypes(void)
|
||||
{
|
||||
/* keyframes */
|
||||
/* selection */
|
||||
WM_operatortype_append(ACT_OT_keyframes_clickselect);
|
||||
WM_operatortype_append(ACT_OT_keyframes_select_all_toggle);
|
||||
WM_operatortype_append(ACT_OT_keyframes_select_border);
|
||||
WM_operatortype_append(ACT_OT_keyframes_select_column);
|
||||
WM_operatortype_append(ACT_OT_clickselect);
|
||||
WM_operatortype_append(ACT_OT_select_all_toggle);
|
||||
WM_operatortype_append(ACT_OT_select_border);
|
||||
WM_operatortype_append(ACT_OT_select_column);
|
||||
|
||||
/* editing */
|
||||
WM_operatortype_append(ACT_OT_keyframes_snap);
|
||||
WM_operatortype_append(ACT_OT_keyframes_mirror);
|
||||
WM_operatortype_append(ACT_OT_keyframes_cfrasnap);
|
||||
WM_operatortype_append(ACT_OT_keyframes_handle_type_set);
|
||||
WM_operatortype_append(ACT_OT_keyframes_interpolation_type);
|
||||
WM_operatortype_append(ACT_OT_keyframes_extrapolation_type_set);
|
||||
WM_operatortype_append(ACT_OT_keyframes_sample);
|
||||
WM_operatortype_append(ACT_OT_keyframes_clean);
|
||||
WM_operatortype_append(ACT_OT_keyframes_delete);
|
||||
WM_operatortype_append(ACT_OT_keyframes_duplicate);
|
||||
WM_operatortype_append(ACT_OT_keyframes_insert);
|
||||
WM_operatortype_append(ACT_OT_keyframes_copy);
|
||||
WM_operatortype_append(ACT_OT_keyframes_paste);
|
||||
WM_operatortype_append(ACT_OT_snap);
|
||||
WM_operatortype_append(ACT_OT_mirror);
|
||||
WM_operatortype_append(ACT_OT_frame_jump);
|
||||
WM_operatortype_append(ACT_OT_handle_type);
|
||||
WM_operatortype_append(ACT_OT_interpolation_type);
|
||||
WM_operatortype_append(ACT_OT_extrapolation_type);
|
||||
WM_operatortype_append(ACT_OT_sample);
|
||||
WM_operatortype_append(ACT_OT_clean);
|
||||
WM_operatortype_append(ACT_OT_delete);
|
||||
WM_operatortype_append(ACT_OT_duplicate);
|
||||
WM_operatortype_append(ACT_OT_insert_keyframe);
|
||||
WM_operatortype_append(ACT_OT_copy);
|
||||
WM_operatortype_append(ACT_OT_paste);
|
||||
|
||||
WM_operatortype_append(ACT_OT_previewrange_set);
|
||||
WM_operatortype_append(ACT_OT_view_all);
|
||||
@@ -95,57 +95,58 @@ static void action_keymap_keyframes (wmWindowManager *wm, ListBase *keymap)
|
||||
|
||||
/* action_select.c - selection tools */
|
||||
/* click-select */
|
||||
WM_keymap_add_item(keymap, "ACT_OT_keyframes_clickselect", SELECTMOUSE, KM_PRESS, 0, 0);
|
||||
kmi= WM_keymap_add_item(keymap, "ACT_OT_keyframes_clickselect", SELECTMOUSE, KM_PRESS, KM_ALT, 0);
|
||||
WM_keymap_add_item(keymap, "ACT_OT_clickselect", SELECTMOUSE, KM_PRESS, 0, 0);
|
||||
kmi= WM_keymap_add_item(keymap, "ACT_OT_clickselect", SELECTMOUSE, KM_PRESS, KM_ALT, 0);
|
||||
RNA_boolean_set(kmi->ptr, "column", 1);
|
||||
kmi= WM_keymap_add_item(keymap, "ACT_OT_keyframes_clickselect", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0);
|
||||
kmi= WM_keymap_add_item(keymap, "ACT_OT_clickselect", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0);
|
||||
RNA_boolean_set(kmi->ptr, "extend", 1);
|
||||
kmi= WM_keymap_add_item(keymap, "ACT_OT_keyframes_clickselect", SELECTMOUSE, KM_PRESS, KM_ALT|KM_SHIFT, 0);
|
||||
kmi= WM_keymap_add_item(keymap, "ACT_OT_clickselect", SELECTMOUSE, KM_PRESS, KM_ALT|KM_SHIFT, 0);
|
||||
RNA_boolean_set(kmi->ptr, "extend", 1);
|
||||
RNA_boolean_set(kmi->ptr, "column", 1);
|
||||
kmi= WM_keymap_add_item(keymap, "ACT_OT_keyframes_clickselect", SELECTMOUSE, KM_PRESS, KM_CTRL, 0);
|
||||
kmi= WM_keymap_add_item(keymap, "ACT_OT_clickselect", SELECTMOUSE, KM_PRESS, KM_CTRL, 0);
|
||||
RNA_enum_set(kmi->ptr, "left_right", ACTKEYS_LRSEL_TEST);
|
||||
|
||||
/* deselect all */
|
||||
WM_keymap_add_item(keymap, "ACT_OT_keyframes_select_all_toggle", AKEY, KM_PRESS, 0, 0);
|
||||
RNA_boolean_set(WM_keymap_add_item(keymap, "ACT_OT_keyframes_select_all_toggle", IKEY, KM_PRESS, KM_CTRL, 0)->ptr, "invert", 1);
|
||||
WM_keymap_add_item(keymap, "ACT_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0);
|
||||
RNA_boolean_set(WM_keymap_add_item(keymap, "ACT_OT_select_all_toggle", IKEY, KM_PRESS, KM_CTRL, 0)->ptr, "invert", 1);
|
||||
|
||||
/* borderselect */
|
||||
WM_keymap_add_item(keymap, "ACT_OT_keyframes_select_border", BKEY, KM_PRESS, 0, 0);
|
||||
RNA_boolean_set(WM_keymap_add_item(keymap, "ACT_OT_keyframes_select_border", BKEY, KM_PRESS, KM_ALT, 0)->ptr, "axis_range", 1);
|
||||
WM_keymap_add_item(keymap, "ACT_OT_select_border", BKEY, KM_PRESS, 0, 0);
|
||||
RNA_boolean_set(WM_keymap_add_item(keymap, "ACT_OT_select_border", BKEY, KM_PRESS, KM_ALT, 0)->ptr, "axis_range", 1);
|
||||
|
||||
/* column select */
|
||||
RNA_enum_set(WM_keymap_add_item(keymap, "ACT_OT_keyframes_select_column", KKEY, KM_PRESS, 0, 0)->ptr, "mode", ACTKEYS_COLUMNSEL_KEYS);
|
||||
RNA_enum_set(WM_keymap_add_item(keymap, "ACT_OT_keyframes_select_column", KKEY, KM_PRESS, KM_CTRL, 0)->ptr, "mode", ACTKEYS_COLUMNSEL_CFRA);
|
||||
RNA_enum_set(WM_keymap_add_item(keymap, "ACT_OT_keyframes_select_column", KKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "mode", ACTKEYS_COLUMNSEL_MARKERS_COLUMN);
|
||||
RNA_enum_set(WM_keymap_add_item(keymap, "ACT_OT_keyframes_select_column", KKEY, KM_PRESS, KM_ALT, 0)->ptr, "mode", ACTKEYS_COLUMNSEL_MARKERS_BETWEEN);
|
||||
RNA_enum_set(WM_keymap_add_item(keymap, "ACT_OT_select_column", KKEY, KM_PRESS, 0, 0)->ptr, "mode", ACTKEYS_COLUMNSEL_KEYS);
|
||||
RNA_enum_set(WM_keymap_add_item(keymap, "ACT_OT_select_column", KKEY, KM_PRESS, KM_CTRL, 0)->ptr, "mode", ACTKEYS_COLUMNSEL_CFRA);
|
||||
RNA_enum_set(WM_keymap_add_item(keymap, "ACT_OT_select_column", KKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "mode", ACTKEYS_COLUMNSEL_MARKERS_COLUMN);
|
||||
RNA_enum_set(WM_keymap_add_item(keymap, "ACT_OT_select_column", KKEY, KM_PRESS, KM_ALT, 0)->ptr, "mode", ACTKEYS_COLUMNSEL_MARKERS_BETWEEN);
|
||||
|
||||
/* action_edit.c */
|
||||
/* snap - current frame to selected keys */
|
||||
WM_keymap_add_item(keymap, "ACT_OT_keyframes_cfrasnap", SKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0);
|
||||
// TODO: maybe since this is called jump, we're better to have it on <something>-J?
|
||||
WM_keymap_add_item(keymap, "ACT_OT_frame_jump", SKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0);
|
||||
|
||||
/* menu + single-step transform */
|
||||
WM_keymap_add_item(keymap, "ACT_OT_keyframes_snap", SKEY, KM_PRESS, KM_SHIFT, 0);
|
||||
WM_keymap_add_item(keymap, "ACT_OT_keyframes_mirror", MKEY, KM_PRESS, KM_SHIFT, 0);
|
||||
WM_keymap_add_item(keymap, "ACT_OT_snap", SKEY, KM_PRESS, KM_SHIFT, 0);
|
||||
WM_keymap_add_item(keymap, "ACT_OT_mirror", MKEY, KM_PRESS, KM_SHIFT, 0);
|
||||
|
||||
/* menu + set setting */
|
||||
WM_keymap_add_item(keymap, "ACT_OT_keyframes_handle_type_set", HKEY, KM_PRESS, 0, 0);
|
||||
WM_keymap_add_item(keymap, "ACT_OT_keyframes_interpolation_type", TKEY, KM_PRESS, KM_SHIFT, 0);
|
||||
WM_keymap_add_item(keymap, "ACT_OT_keyframes_extrapolation_type_set", EKEY, KM_PRESS, KM_SHIFT, 0);
|
||||
WM_keymap_add_item(keymap, "ACT_OT_handle_type", HKEY, KM_PRESS, 0, 0);
|
||||
WM_keymap_add_item(keymap, "ACT_OT_interpolation_type", TKEY, KM_PRESS, KM_SHIFT, 0);
|
||||
WM_keymap_add_item(keymap, "ACT_OT_extrapolation_type", EKEY, KM_PRESS, KM_SHIFT, 0);
|
||||
|
||||
/* destructive */
|
||||
WM_keymap_add_item(keymap, "ACT_OT_keyframes_clean", OKEY, KM_PRESS, 0, 0);
|
||||
WM_keymap_add_item(keymap, "ACT_OT_keyframes_sample", OKEY, KM_PRESS, KM_SHIFT, 0);
|
||||
WM_keymap_add_item(keymap, "ACT_OT_clean", OKEY, KM_PRESS, 0, 0);
|
||||
WM_keymap_add_item(keymap, "ACT_OT_sample", OKEY, KM_PRESS, KM_SHIFT, 0);
|
||||
|
||||
WM_keymap_add_item(keymap, "ACT_OT_keyframes_delete", XKEY, KM_PRESS, 0, 0);
|
||||
WM_keymap_add_item(keymap, "ACT_OT_keyframes_delete", DELKEY, KM_PRESS, 0, 0);
|
||||
WM_keymap_add_item(keymap, "ACT_OT_delete", XKEY, KM_PRESS, 0, 0);
|
||||
WM_keymap_add_item(keymap, "ACT_OT_delete", DELKEY, KM_PRESS, 0, 0);
|
||||
|
||||
WM_keymap_add_item(keymap, "ACT_OT_keyframes_duplicate", DKEY, KM_PRESS, KM_SHIFT, 0);
|
||||
WM_keymap_add_item(keymap, "ACT_OT_keyframes_insert", IKEY, KM_PRESS, 0, 0);
|
||||
WM_keymap_add_item(keymap, "ACT_OT_duplicate", DKEY, KM_PRESS, KM_SHIFT, 0);
|
||||
WM_keymap_add_item(keymap, "ACT_OT_insert_keyframe", IKEY, KM_PRESS, 0, 0);
|
||||
|
||||
/* copy/paste */
|
||||
WM_keymap_add_item(keymap, "ACT_OT_keyframes_copy", CKEY, KM_PRESS, KM_CTRL, 0);
|
||||
WM_keymap_add_item(keymap, "ACT_OT_keyframes_paste", VKEY, KM_PRESS, KM_CTRL, 0);
|
||||
WM_keymap_add_item(keymap, "ACT_OT_copy", CKEY, KM_PRESS, KM_CTRL, 0);
|
||||
WM_keymap_add_item(keymap, "ACT_OT_paste", VKEY, KM_PRESS, KM_CTRL, 0);
|
||||
|
||||
/* auto-set range */
|
||||
WM_keymap_add_item(keymap, "ACT_OT_previewrange_set", PKEY, KM_PRESS, KM_CTRL|KM_ALT, 0);
|
||||
|
||||
@@ -64,6 +64,7 @@
|
||||
#include "BKE_fcurve.h"
|
||||
#include "BKE_key.h"
|
||||
#include "BKE_material.h"
|
||||
#include "BKE_nla.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_utildefines.h"
|
||||
@@ -173,21 +174,21 @@ static int actkeys_deselectall_exec(bContext *C, wmOperator *op)
|
||||
else
|
||||
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!
|
||||
/* set notifier that keyframe selection have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_SELECT, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void ACT_OT_keyframes_select_all_toggle (wmOperatorType *ot)
|
||||
void ACT_OT_select_all_toggle (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Select All";
|
||||
ot->idname= "ACT_OT_keyframes_select_all_toggle";
|
||||
ot->idname= "ACT_OT_select_all_toggle";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= actkeys_deselectall_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= ED_operator_action_active;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -222,7 +223,8 @@ static void borderselect_action (bAnimContext *ac, rcti rect, short mode, short
|
||||
BeztEditFunc ok_cb, select_cb;
|
||||
View2D *v2d= &ac->ar->v2d;
|
||||
rctf rectf;
|
||||
float ymin=0, ymax=(float)(-ACHANNEL_HEIGHT);
|
||||
//float ymin=0, ymax=(float)(-ACHANNEL_HEIGHT);
|
||||
float ymin=0, ymax=(float)(-ACHANNEL_HEIGHT_HALF);
|
||||
|
||||
/* convert mouse coordinates to frame ranges and channel coordinates corrected for view pan/zoom */
|
||||
UI_view2d_region_to_view(v2d, rect.xmin, rect.ymin+2, &rectf.xmin, &rectf.ymin);
|
||||
@@ -245,7 +247,7 @@ static void borderselect_action (bAnimContext *ac, rcti rect, short mode, short
|
||||
|
||||
/* loop over data, doing border select */
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
Object *nob= ANIM_nla_mapping_get(ac, ale);
|
||||
AnimData *adt= ANIM_nla_mapping_get(ac, ale);
|
||||
|
||||
/* get new vertical minimum extent of channel */
|
||||
ymin= ymax - ACHANNEL_STEP;
|
||||
@@ -253,9 +255,9 @@ static void borderselect_action (bAnimContext *ac, rcti rect, short mode, short
|
||||
/* set horizontal range (if applicable) */
|
||||
if (ELEM(mode, ACTKEYS_BORDERSEL_FRAMERANGE, ACTKEYS_BORDERSEL_ALLKEYS)) {
|
||||
/* if channel is mapped in NLA, apply correction */
|
||||
if (nob) {
|
||||
bed.f1= get_action_frame(nob, rectf.xmin);
|
||||
bed.f2= get_action_frame(nob, rectf.xmax);
|
||||
if (adt) {
|
||||
bed.f1= BKE_nla_tweakedit_remap(adt, rectf.xmin, NLATIME_CONVERT_UNMAP);
|
||||
bed.f2= BKE_nla_tweakedit_remap(adt, rectf.xmax, NLATIME_CONVERT_UNMAP);
|
||||
}
|
||||
else {
|
||||
bed.f1= rectf.xmin;
|
||||
@@ -335,21 +337,24 @@ static int actkeys_borderselect_exec(bContext *C, wmOperator *op)
|
||||
/* apply borderselect action */
|
||||
borderselect_action(&ac, rect, mode, selectmode);
|
||||
|
||||
/* set notifier that keyframe selection have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_SELECT, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void ACT_OT_keyframes_select_border(wmOperatorType *ot)
|
||||
void ACT_OT_select_border(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Border Select";
|
||||
ot->idname= "ACT_OT_keyframes_select_border";
|
||||
ot->idname= "ACT_OT_select_border";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke= WM_border_select_invoke;
|
||||
ot->exec= actkeys_borderselect_exec;
|
||||
ot->modal= WM_border_select_modal;
|
||||
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= ED_operator_action_active;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -413,12 +418,12 @@ static void markers_selectkeys_between (bAnimContext *ac)
|
||||
|
||||
/* select keys in-between */
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
Object *nob= ANIM_nla_mapping_get(ac, ale);
|
||||
AnimData *adt= ANIM_nla_mapping_get(ac, ale);
|
||||
|
||||
if (nob) {
|
||||
ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 0, 1);
|
||||
if (adt) {
|
||||
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
|
||||
ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL);
|
||||
ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 1, 1);
|
||||
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
|
||||
}
|
||||
else {
|
||||
ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL);
|
||||
@@ -495,15 +500,15 @@ static void columnselect_action_keys (bAnimContext *ac, short mode)
|
||||
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
|
||||
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
Object *nob= ANIM_nla_mapping_get(ac, ale);
|
||||
AnimData *adt= ANIM_nla_mapping_get(ac, ale);
|
||||
|
||||
/* loop over cfraelems (stored in the BeztEditData->list)
|
||||
* - we need to do this here, as we can apply fewer NLA-mapping conversions
|
||||
*/
|
||||
for (ce= bed.list.first; ce; ce= ce->next) {
|
||||
/* set frame for validation callback to refer to */
|
||||
if (nob)
|
||||
bed.f1= get_action_frame(nob, ce->cfra);
|
||||
if (adt)
|
||||
bed.f1= BKE_nla_tweakedit_remap(adt, ce->cfra, NLATIME_CONVERT_UNMAP);
|
||||
else
|
||||
bed.f1= ce->cfra;
|
||||
|
||||
@@ -549,21 +554,21 @@ static int actkeys_columnselect_exec(bContext *C, wmOperator *op)
|
||||
else
|
||||
columnselect_action_keys(&ac, mode);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_SELECT);
|
||||
/* set notifier that keyframe selection have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_SELECT, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void ACT_OT_keyframes_select_column (wmOperatorType *ot)
|
||||
void ACT_OT_select_column (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Select All";
|
||||
ot->idname= "ACT_OT_keyframes_select_column";
|
||||
ot->idname= "ACT_OT_select_column";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= actkeys_columnselect_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= ED_operator_action_active;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -641,7 +646,7 @@ static void actkeys_mselect_leftright (bAnimContext *ac, short leftright, short
|
||||
|
||||
memset(&bed, 0, sizeof(BeztEditFunc));
|
||||
if (leftright == ACTKEYS_LRSEL_LEFT) {
|
||||
bed.f1 = -MAXFRAMEF;
|
||||
bed.f1 = MINAFRAMEF;
|
||||
bed.f2 = (float)(CFRA + FRAME_CLICK_THRESH);
|
||||
}
|
||||
else {
|
||||
@@ -658,12 +663,12 @@ static void actkeys_mselect_leftright (bAnimContext *ac, short leftright, short
|
||||
|
||||
/* select keys on the side where most data occurs */
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
Object *nob= ANIM_nla_mapping_get(ac, ale);
|
||||
AnimData *adt= ANIM_nla_mapping_get(ac, ale);
|
||||
|
||||
if (nob) {
|
||||
ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 0, 1);
|
||||
if (adt) {
|
||||
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
|
||||
ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL);
|
||||
ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 1, 1);
|
||||
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
|
||||
}
|
||||
//else if (ale->type == ANIMTYPE_GPLAYER)
|
||||
// borderselect_gplayer_frames(ale->data, min, max, SELECT_ADD);
|
||||
@@ -702,11 +707,11 @@ static void actkeys_mselect_column(bAnimContext *ac, short select_mode, float se
|
||||
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
|
||||
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
Object *nob= ANIM_nla_mapping_get(ac, ale);
|
||||
AnimData *adt= ANIM_nla_mapping_get(ac, ale);
|
||||
|
||||
/* set frame for validation callback to refer to */
|
||||
if (nob)
|
||||
bed.f1= get_action_frame(nob, selx);
|
||||
if (adt)
|
||||
bed.f1= BKE_nla_tweakedit_remap(adt, selx, NLATIME_CONVERT_UNMAP);
|
||||
else
|
||||
bed.f1= selx;
|
||||
|
||||
@@ -742,12 +747,16 @@ static void mouse_action_keys (bAnimContext *ac, int mval[2], short select_mode,
|
||||
int filter;
|
||||
|
||||
View2D *v2d= &ac->ar->v2d;
|
||||
bDopeSheet *ads = NULL;
|
||||
int channel_index;
|
||||
short found = 0;
|
||||
float selx = 0.0f;
|
||||
float x, y;
|
||||
rctf rectf;
|
||||
|
||||
/* get dopesheet info */
|
||||
if (ac->datatype == ANIMCONT_DOPESHEET)
|
||||
ads= ac->data;
|
||||
|
||||
/* use View2D to determine the index of the channel (i.e a row in the list) where keyframe was */
|
||||
UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
|
||||
@@ -766,51 +775,41 @@ 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 {
|
||||
/* found match - must return here... */
|
||||
Object *nob= ANIM_nla_mapping_get(ac, ale);
|
||||
ActKeysInc *aki= init_aki_data(ac, ale);
|
||||
AnimData *adt= ANIM_nla_mapping_get(ac, ale);
|
||||
ActKeyColumn *ak;
|
||||
float xmin, xmax;
|
||||
|
||||
/* apply NLA-scaling correction? */
|
||||
if (nob) {
|
||||
xmin= get_action_frame(nob, rectf.xmin);
|
||||
xmax= get_action_frame(nob, rectf.xmax);
|
||||
}
|
||||
else {
|
||||
xmin= rectf.xmin;
|
||||
xmax= rectf.xmax;
|
||||
}
|
||||
|
||||
/* make list of keyframes */
|
||||
// TODO: it would be great if we didn't have to apply this to all the keyframes to do this...
|
||||
if (ale->key_data) {
|
||||
switch (ale->datatype) {
|
||||
case ALE_OB:
|
||||
{
|
||||
Object *ob= (Object *)ale->key_data;
|
||||
ob_to_keylist(ob, &anim_keys, NULL, aki);
|
||||
ob_to_keylist(ads, ob, &anim_keys, NULL);
|
||||
}
|
||||
break;
|
||||
case ALE_ACT:
|
||||
{
|
||||
bAction *act= (bAction *)ale->key_data;
|
||||
action_to_keylist(act, &anim_keys, NULL, aki);
|
||||
action_to_keylist(adt, act, &anim_keys, NULL);
|
||||
}
|
||||
break;
|
||||
case ALE_FCURVE:
|
||||
{
|
||||
FCurve *fcu= (FCurve *)ale->key_data;
|
||||
fcurve_to_keylist(fcu, &anim_keys, NULL, aki);
|
||||
fcurve_to_keylist(adt, fcu, &anim_keys, NULL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (ale->type == ANIMTYPE_GROUP) {
|
||||
bActionGroup *agrp= (bActionGroup *)ale->data;
|
||||
agroup_to_keylist(agrp, &anim_keys, NULL, aki);
|
||||
agroup_to_keylist(adt, agrp, &anim_keys, NULL);
|
||||
}
|
||||
else if (ale->type == ANIMTYPE_GPDATABLOCK) {
|
||||
/* cleanup */
|
||||
@@ -820,13 +819,17 @@ static void mouse_action_keys (bAnimContext *ac, int mval[2], short select_mode,
|
||||
}
|
||||
else if (ale->type == ANIMTYPE_GPLAYER) {
|
||||
bGPDlayer *gpl= (bGPDlayer *)ale->data;
|
||||
gpl_to_keylist(gpl, &anim_keys, NULL, aki);
|
||||
gpl_to_keylist(ads, gpl, &anim_keys, NULL);
|
||||
}
|
||||
|
||||
/* loop through keyframes, finding one that was clicked on */
|
||||
for (ak= anim_keys.first; ak; ak= ak->next) {
|
||||
if (IN_RANGE(ak->cfra, xmin, xmax)) {
|
||||
selx= ak->cfra;
|
||||
if (IN_RANGE(ak->cfra, rectf.xmin, rectf.xmax)) {
|
||||
/* set the frame to use, and apply inverse-correction for NLA-mapping
|
||||
* so that the frame will get selected by the selection functiosn without
|
||||
* requiring to map each frame once again...
|
||||
*/
|
||||
selx= BKE_nla_tweakedit_remap(adt, ak->cfra, NLATIME_CONVERT_UNMAP);
|
||||
found= 1;
|
||||
break;
|
||||
}
|
||||
@@ -857,17 +860,19 @@ static void mouse_action_keys (bAnimContext *ac, int mval[2], short select_mode,
|
||||
ANIM_deselect_anim_channels(ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
|
||||
|
||||
/* Highlight Action-Group or F-Curve? */
|
||||
if (ale->type == ANIMTYPE_GROUP) {
|
||||
bActionGroup *agrp= ale->data;
|
||||
|
||||
agrp->flag |= AGRP_SELECTED;
|
||||
ANIM_set_active_channel(ac->data, ac->datatype, filter, agrp, ANIMTYPE_GROUP);
|
||||
}
|
||||
else if (ale->type == ANIMTYPE_FCURVE) {
|
||||
FCurve *fcu= ale->data;
|
||||
|
||||
fcu->flag |= FCURVE_SELECTED;
|
||||
ANIM_set_active_channel(ac->data, ac->datatype, filter, fcu, ANIMTYPE_FCURVE);
|
||||
if (ale && ale->data) {
|
||||
if (ale->type == ANIMTYPE_GROUP) {
|
||||
bActionGroup *agrp= ale->data;
|
||||
|
||||
agrp->flag |= AGRP_SELECTED;
|
||||
ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, agrp, ANIMTYPE_GROUP);
|
||||
}
|
||||
else if (ale->type == ANIMTYPE_FCURVE) {
|
||||
FCurve *fcu= ale->data;
|
||||
|
||||
fcu->flag |= FCURVE_SELECTED;
|
||||
ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ANIMTYPE_FCURVE);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ac->datatype == ANIMCONT_GPENCIL) {
|
||||
@@ -881,18 +886,20 @@ static void mouse_action_keys (bAnimContext *ac, int mval[2], short select_mode,
|
||||
|
||||
/* only select keyframes if we clicked on a valid channel and hit something */
|
||||
if (ale) {
|
||||
/* apply selection to keyframes */
|
||||
if (/*gpl*/0) {
|
||||
/* grease pencil */
|
||||
//select_gpencil_frame(gpl, (int)selx, selectmode);
|
||||
}
|
||||
else if (column) {
|
||||
/* select all keyframes in the same frame as the one we hit on the active channel */
|
||||
actkeys_mselect_column(ac, select_mode, selx);
|
||||
}
|
||||
else {
|
||||
/* select the nominated keyframe on the given frame */
|
||||
actkeys_mselect_single(ac, ale, select_mode, selx);
|
||||
if (found) {
|
||||
/* apply selection to keyframes */
|
||||
if (/*gpl*/0) {
|
||||
/* grease pencil */
|
||||
//select_gpencil_frame(gpl, (int)selx, selectmode);
|
||||
}
|
||||
else if (column) {
|
||||
/* select all keyframes in the same frame as the one we hit on the active channel */
|
||||
actkeys_mselect_column(ac, select_mode, selx);
|
||||
}
|
||||
else {
|
||||
/* select the nominated keyframe on the given frame */
|
||||
actkeys_mselect_single(ac, ale, select_mode, selx);
|
||||
}
|
||||
}
|
||||
|
||||
/* free this channel */
|
||||
@@ -950,22 +957,22 @@ static int actkeys_clickselect_invoke(bContext *C, wmOperator *op, wmEvent *even
|
||||
mouse_action_keys(&ac, mval, selectmode, column);
|
||||
}
|
||||
|
||||
/* set notifier that things have changed */
|
||||
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH);
|
||||
/* set notifier that keyframe selection (and channels too) have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_SELECT|ND_ANIMCHAN_SELECT, NULL);
|
||||
|
||||
/* for tweak grab to work */
|
||||
return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH;
|
||||
}
|
||||
|
||||
void ACT_OT_keyframes_clickselect (wmOperatorType *ot)
|
||||
void ACT_OT_clickselect (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Mouse Select Keys";
|
||||
ot->idname= "ACT_OT_keyframes_clickselect";
|
||||
ot->idname= "ACT_OT_clickselect";
|
||||
|
||||
/* api callbacks - absolutely no exec() this yet... */
|
||||
ot->invoke= actkeys_clickselect_invoke;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= ED_operator_action_active;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
|
||||
@@ -288,6 +288,9 @@ static void action_channel_area_listener(ARegion *ar, wmNotifier *wmn)
|
||||
{
|
||||
/* context changes */
|
||||
switch(wmn->category) {
|
||||
case NC_ANIMATION:
|
||||
ED_region_tag_redraw(ar);
|
||||
break;
|
||||
case NC_SCENE:
|
||||
switch(wmn->data) {
|
||||
case ND_OB_ACTIVE:
|
||||
@@ -314,6 +317,9 @@ static void action_main_area_listener(ARegion *ar, wmNotifier *wmn)
|
||||
{
|
||||
/* context changes */
|
||||
switch(wmn->category) {
|
||||
case NC_ANIMATION:
|
||||
ED_region_tag_redraw(ar);
|
||||
break;
|
||||
case NC_SCENE:
|
||||
switch(wmn->data) {
|
||||
case ND_OB_ACTIVE:
|
||||
@@ -344,6 +350,9 @@ static void action_listener(ScrArea *sa, wmNotifier *wmn)
|
||||
{
|
||||
/* context changes */
|
||||
switch (wmn->category) {
|
||||
case NC_ANIMATION:
|
||||
ED_area_tag_refresh(sa);
|
||||
break;
|
||||
case NC_SCENE:
|
||||
/*switch (wmn->data) {
|
||||
case ND_OB_ACTIVE:
|
||||
|
||||
@@ -193,7 +193,7 @@ void buttons_header_buttons(const bContext *C, ARegion *ar)
|
||||
uiBlockEndAlign(block);
|
||||
|
||||
xco+=XIC;
|
||||
uiDefButI(block, NUM, B_NEWFRAME, "", (xco+20),yco,60,YIC, &(CTX_data_scene(C)->r.cfra), 1.0, MAXFRAMEF, 0, 0, "Displays Current Frame of animation. Click to change.");
|
||||
uiDefButI(block, NUM, B_NEWFRAME, "", (xco+20),yco,60,YIC, &(CTX_data_scene(C)->r.cfra), MINAFRAMEF, MAXFRAMEF, 0, 0, "Displays Current Frame of animation. Click to change.");
|
||||
xco+= 80;
|
||||
|
||||
/* always as last */
|
||||
|
||||
@@ -147,6 +147,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);
|
||||
|
||||
|
||||
@@ -347,6 +347,7 @@ static void graph_panel_drivers(const bContext *C, Panel *pa)
|
||||
}
|
||||
|
||||
/* ******************* f-modifiers ******************************** */
|
||||
/* all the drawing code is in editors/animation/fmodifier_ui.c */
|
||||
|
||||
#define B_FMODIFIER_REDRAW 20
|
||||
|
||||
@@ -360,671 +361,41 @@ static void do_graph_region_modifier_buttons(bContext *C, void *arg, int event)
|
||||
}
|
||||
}
|
||||
|
||||
/* macro for use here to draw background box and set height */
|
||||
// XXX for now, roundbox has it's callback func set to NULL to not intercept events
|
||||
#define DRAW_BACKDROP(height) \
|
||||
{ \
|
||||
uiDefBut(block, ROUNDBOX, B_REDR, "", -3, *yco-height, width+3, height-1, NULL, 5.0, 0.0, 12.0, (float)rb_col, ""); \
|
||||
}
|
||||
|
||||
/* callback to verify modifier data */
|
||||
static void validate_fmodifier_cb (bContext *C, void *fcu_v, void *fcm_v)
|
||||
{
|
||||
FModifier *fcm= (FModifier *)fcm_v;
|
||||
FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
|
||||
|
||||
/* call the verify callback on the modifier if applicable */
|
||||
if (fmi && fmi->verify_data)
|
||||
fmi->verify_data(fcm);
|
||||
}
|
||||
|
||||
/* callback to set the active modifier */
|
||||
static void activate_fmodifier_cb (bContext *C, void *fcu_v, void *fcm_v)
|
||||
{
|
||||
FCurve *fcu= (FCurve *)fcu_v;
|
||||
FModifier *fcm= (FModifier *)fcm_v;
|
||||
|
||||
/* call API function to set the active modifier for active F-Curve */
|
||||
fcurve_set_active_modifier(fcu, fcm);
|
||||
}
|
||||
|
||||
/* callback to remove the given modifier */
|
||||
static void delete_fmodifier_cb (bContext *C, void *fcu_v, void *fcm_v)
|
||||
{
|
||||
FCurve *fcu= (FCurve *)fcu_v;
|
||||
FModifier *fcm= (FModifier *)fcm_v;
|
||||
|
||||
/* remove the given F-Modifier from the F-Curve */
|
||||
fcurve_remove_modifier(fcu, fcm);
|
||||
}
|
||||
|
||||
/* --------------- */
|
||||
|
||||
/* draw settings for generator modifier */
|
||||
static void draw_modifier__generator(uiBlock *block, FCurve *fcu, FModifier *fcm, int *yco, short *height, short width, short active, int rb_col)
|
||||
{
|
||||
FMod_Generator *data= (FMod_Generator *)fcm->data;
|
||||
char gen_mode[]="Generator Type%t|Expanded Polynomial%x0|Factorised Polynomial%x1|Built-In Function%x2|Expression%x3";
|
||||
char fn_type[]="Built-In Function%t|Sin%x0|Cos%x1|Tan%x2|Square Root%x3|Natural Log%x4";
|
||||
int cy= *yco - 30;
|
||||
uiBut *but;
|
||||
|
||||
/* set the height */
|
||||
(*height) = 90;
|
||||
switch (data->mode) {
|
||||
case FCM_GENERATOR_POLYNOMIAL: /* polynomial expression */
|
||||
(*height) += 20*(data->poly_order+1) + 20;
|
||||
break;
|
||||
case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* factorised polynomial */
|
||||
(*height) += 20 * data->poly_order + 15;
|
||||
break;
|
||||
case FCM_GENERATOR_FUNCTION: /* builtin function */
|
||||
(*height) += 55; // xxx
|
||||
break;
|
||||
case FCM_GENERATOR_EXPRESSION: /* py-expression */
|
||||
// xxx nothing to draw
|
||||
break;
|
||||
}
|
||||
|
||||
/* basic settings (backdrop + mode selector + some padding) */
|
||||
DRAW_BACKDROP((*height));
|
||||
uiBlockBeginAlign(block);
|
||||
but= uiDefButS(block, MENU, B_FMODIFIER_REDRAW, gen_mode, 10,cy,width-30,19, &data->mode, 0, 0, 0, 0, "Selects type of generator algorithm.");
|
||||
uiButSetFunc(but, validate_fmodifier_cb, fcu, fcm);
|
||||
cy -= 20;
|
||||
|
||||
uiDefButBitS(block, TOG, FCM_GENERATOR_ADDITIVE, B_FMODIFIER_REDRAW, "Additive", 10,cy,width-30,19, &data->flag, 0, 0, 0, 0, "Values generated by this modifier are applied on top of the existing values instead of overwriting them");
|
||||
cy -= 35;
|
||||
uiBlockEndAlign(block);
|
||||
|
||||
/* now add settings for individual modes */
|
||||
switch (data->mode) {
|
||||
case FCM_GENERATOR_POLYNOMIAL: /* polynomial expression */
|
||||
{
|
||||
float *cp = NULL;
|
||||
char xval[32];
|
||||
unsigned int i;
|
||||
|
||||
/* draw polynomial order selector */
|
||||
but= uiDefButS(block, NUM, B_FMODIFIER_REDRAW, "Poly Order: ", 10,cy,width-30,19, &data->poly_order, 1, 100, 0, 0, "'Order' of the Polynomial - for a polynomial with n terms, 'order' is n-1");
|
||||
uiButSetFunc(but, validate_fmodifier_cb, fcu, fcm);
|
||||
cy -= 35;
|
||||
|
||||
/* draw controls for each coefficient and a + sign at end of row */
|
||||
uiDefBut(block, LABEL, 1, "y = ", 0, cy, 50, 20, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
cp= data->coefficients;
|
||||
for (i=0; (i < data->arraysize) && (cp); i++, cp++) {
|
||||
/* coefficient */
|
||||
uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 50, cy, 150, 20, cp, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "Coefficient for polynomial");
|
||||
|
||||
/* 'x' param (and '+' if necessary) */
|
||||
if (i == 0)
|
||||
strcpy(xval, "");
|
||||
else if (i == 1)
|
||||
strcpy(xval, "x");
|
||||
else
|
||||
sprintf(xval, "x^%d", i);
|
||||
uiDefBut(block, LABEL, 1, xval, 200, cy, 50, 20, NULL, 0.0, 0.0, 0, 0, "Power of x");
|
||||
|
||||
if ( (i != (data->arraysize - 1)) || ((i==0) && data->arraysize==2) )
|
||||
uiDefBut(block, LABEL, 1, "+", 250, cy, 30, 20, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
cy -= 20;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* factorised polynomial expression */
|
||||
{
|
||||
float *cp = NULL;
|
||||
unsigned int i;
|
||||
|
||||
/* draw polynomial order selector */
|
||||
but= uiDefButS(block, NUM, B_FMODIFIER_REDRAW, "Poly Order: ", 10,cy,width-30,19, &data->poly_order, 1, 100, 0, 0, "'Order' of the Polynomial - for a polynomial with n terms, 'order' is n-1");
|
||||
uiButSetFunc(but, validate_fmodifier_cb, fcu, fcm);
|
||||
cy -= 35;
|
||||
|
||||
/* draw controls for each pair of coefficients */
|
||||
uiDefBut(block, LABEL, 1, "y = ", 0, cy, 50, 20, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
cp= data->coefficients;
|
||||
for (i=0; (i < data->poly_order) && (cp); i++, cp+=2) {
|
||||
/* opening bracket */
|
||||
uiDefBut(block, LABEL, 1, "(", 40, cy, 50, 20, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
/* coefficients */
|
||||
uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 50, cy, 100, 20, cp, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "Coefficient of x");
|
||||
|
||||
uiDefBut(block, LABEL, 1, "x + ", 150, cy, 30, 20, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 180, cy, 100, 20, cp+1, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "Second coefficient");
|
||||
|
||||
/* closing bracket and '+' sign */
|
||||
if ( (i != (data->poly_order - 1)) || ((i==0) && data->poly_order==2) )
|
||||
uiDefBut(block, LABEL, 1, ") ◊", 280, cy, 30, 20, NULL, 0.0, 0.0, 0, 0, "");
|
||||
else
|
||||
uiDefBut(block, LABEL, 1, ")", 280, cy, 30, 20, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
cy -= 20;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case FCM_GENERATOR_FUNCTION: /* built-in function */
|
||||
{
|
||||
float *cp= data->coefficients;
|
||||
|
||||
/* draw function selector */
|
||||
but= uiDefButS(block, MENU, B_FMODIFIER_REDRAW, fn_type, 10,cy,width-30,19, &data->func_type, 0, 0, 0, 0, "Built-In Function to use");
|
||||
uiButSetFunc(but, validate_fmodifier_cb, fcu, fcm);
|
||||
cy -= 35;
|
||||
|
||||
/* draw controls for equation of coefficients */
|
||||
/* row 1 */
|
||||
{
|
||||
uiDefBut(block, LABEL, 1, "y = ", 0, cy, 50, 20, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 50, cy, 150, 20, cp+3, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "Coefficient (D) for function");
|
||||
uiDefBut(block, LABEL, 1, "+", 200, cy, 30, 20, NULL, 0.0, 0.0, 0, 0, "");
|
||||
cy -= 20;
|
||||
}
|
||||
|
||||
/* row 2 */
|
||||
{
|
||||
char func_name[32];
|
||||
|
||||
/* coefficient outside bracket */
|
||||
uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 5, cy, 80, 20, cp, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "Coefficient (A) for function");
|
||||
|
||||
/* opening bracket */
|
||||
switch (data->func_type)
|
||||
{
|
||||
case FCM_GENERATOR_FN_SIN: /* sine wave */
|
||||
sprintf(func_name, "sin(");
|
||||
break;
|
||||
case FCM_GENERATOR_FN_COS: /* cosine wave */
|
||||
sprintf(func_name, "cos(");
|
||||
break;
|
||||
case FCM_GENERATOR_FN_TAN: /* tangent wave */
|
||||
sprintf(func_name, "tan(");
|
||||
break;
|
||||
case FCM_GENERATOR_FN_LN: /* natural log */
|
||||
sprintf(func_name, "ln(");
|
||||
break;
|
||||
case FCM_GENERATOR_FN_SQRT: /* square root */
|
||||
sprintf(func_name, "sqrt(");
|
||||
break;
|
||||
default: /* unknown */
|
||||
sprintf(func_name, "<fn?>(");
|
||||
break;
|
||||
}
|
||||
uiDefBut(block, LABEL, 1, func_name, 85, cy, 40, 20, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
/* coefficients inside bracket */
|
||||
uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 120, cy, 75, 20, cp+1, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "Coefficient (B) of x");
|
||||
|
||||
uiDefBut(block, LABEL, 1, "x+", 195, cy, 30, 20, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 225, cy, 80, 20, cp+2, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "Coefficient (C) of function");
|
||||
|
||||
/* closing bracket */
|
||||
uiDefBut(block, LABEL, 1, ")", 300, cy, 30, 20, NULL, 0.0, 0.0, 0, 0, "");
|
||||
cy -= 20;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case FCM_GENERATOR_EXPRESSION: /* py-expression */
|
||||
// TODO...
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------- */
|
||||
|
||||
/* draw settings for cycles modifier */
|
||||
static void draw_modifier__cycles(uiBlock *block, FCurve *fcu, FModifier *fcm, int *yco, short *height, short width, short active, int rb_col)
|
||||
{
|
||||
FMod_Cycles *data= (FMod_Cycles *)fcm->data;
|
||||
char cyc_mode[]="Cycling Mode%t|No Cycles%x0|Repeat Motion%x1|Repeat with Offset%x2|Repeat Mirrored%x3";
|
||||
int cy= (*yco - 30), cy1= (*yco - 50), cy2= (*yco - 70);
|
||||
|
||||
/* set the height */
|
||||
(*height) = 80;
|
||||
|
||||
/* basic settings (backdrop + some padding) */
|
||||
DRAW_BACKDROP((*height));
|
||||
|
||||
/* 'before' range */
|
||||
uiDefBut(block, LABEL, 1, "Before:", 4, cy, 80, 20, NULL, 0.0, 0.0, 0, 0, "Settings for cycling before first keyframe");
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefButS(block, MENU, B_FMODIFIER_REDRAW, cyc_mode, 3,cy1,150,20, &data->before_mode, 0, 0, 0, 0, "Cycling mode to use before first keyframe");
|
||||
uiDefButS(block, NUM, B_FMODIFIER_REDRAW, "Max Cycles:", 3, cy2, 150, 20, &data->before_cycles, 0, 10000, 10, 3, "Maximum number of cycles to allow (0 = infinite)");
|
||||
uiBlockEndAlign(block);
|
||||
|
||||
/* 'after' range */
|
||||
uiDefBut(block, LABEL, 1, "After:", 155, cy, 80, 20, NULL, 0.0, 0.0, 0, 0, "Settings for cycling after last keyframe");
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefButS(block, MENU, B_FMODIFIER_REDRAW, cyc_mode, 157,cy1,150,20, &data->after_mode, 0, 0, 0, 0, "Cycling mode to use after first keyframe");
|
||||
uiDefButS(block, NUM, B_FMODIFIER_REDRAW, "Max Cycles:", 157, cy2, 150, 20, &data->after_cycles, 0, 10000, 10, 3, "Maximum number of cycles to allow (0 = infinite)");
|
||||
uiBlockEndAlign(block);
|
||||
}
|
||||
|
||||
/* --------------- */
|
||||
|
||||
/* draw settings for noise modifier */
|
||||
static void draw_modifier__noise(uiBlock *block, FCurve *fcu, FModifier *fcm, int *yco, short *height, short width, short active, int rb_col)
|
||||
{
|
||||
FMod_Noise *data= (FMod_Noise *)fcm->data;
|
||||
int cy= (*yco - 30), cy1= (*yco - 50), cy2= (*yco - 70);
|
||||
char cyc_mode[]="Modification %t|Replace %x0|Add %x1|Subtract %x2|Multiply %x3";
|
||||
|
||||
/* set the height */
|
||||
(*height) = 80;
|
||||
|
||||
/* basic settings (backdrop + some padding) */
|
||||
DRAW_BACKDROP((*height));
|
||||
|
||||
uiDefButS(block, MENU, B_FMODIFIER_REDRAW, cyc_mode,
|
||||
3, cy, 150, 20, &data->modification, 0, 0, 0, 0, "Method of modifying the existing F-Curve use before first keyframe");
|
||||
|
||||
uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Size:",
|
||||
3, cy1, 150, 20, &data->size, 0.000001, 10000.0, 0.01, 3, "");
|
||||
uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Strength:",
|
||||
3, cy2, 150, 20, &data->strength, 0.0, 10000.0, 0.01, 3, "");
|
||||
|
||||
uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Phase:",
|
||||
155, cy1, 150, 20, &data->phase, 0.0, 100000.0, 0.1, 3, "");
|
||||
uiDefButS(block, NUM, B_FMODIFIER_REDRAW, "Depth:",
|
||||
155, cy2, 150, 20, &data->depth, 0, 128, 1, 3, "");
|
||||
|
||||
}
|
||||
|
||||
/* --------------- */
|
||||
|
||||
#define BINARYSEARCH_FRAMEEQ_THRESH 0.0001
|
||||
|
||||
/* Binary search algorithm for finding where to insert Envelope Data Point.
|
||||
* Returns the index to insert at (data already at that index will be offset if replace is 0)
|
||||
*/
|
||||
static int binarysearch_fcm_envelopedata_index (FCM_EnvelopeData array[], float frame, int arraylen, short *exists)
|
||||
{
|
||||
int start=0, end=arraylen;
|
||||
int loopbreaker= 0, maxloop= arraylen * 2;
|
||||
|
||||
/* initialise exists-flag first */
|
||||
*exists= 0;
|
||||
|
||||
/* sneaky optimisations (don't go through searching process if...):
|
||||
* - keyframe to be added is to be added out of current bounds
|
||||
* - keyframe to be added would replace one of the existing ones on bounds
|
||||
*/
|
||||
if ((arraylen <= 0) || (array == NULL)) {
|
||||
printf("Warning: binarysearch_fcm_envelopedata_index() encountered invalid array \n");
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
/* check whether to add before/after/on */
|
||||
float framenum;
|
||||
|
||||
/* 'First' Point (when only one point, this case is used) */
|
||||
framenum= array[0].time;
|
||||
if (IS_EQT(frame, framenum, BINARYSEARCH_FRAMEEQ_THRESH)) {
|
||||
*exists = 1;
|
||||
return 0;
|
||||
}
|
||||
else if (frame < framenum)
|
||||
return 0;
|
||||
|
||||
/* 'Last' Point */
|
||||
framenum= array[(arraylen-1)].time;
|
||||
if (IS_EQT(frame, framenum, BINARYSEARCH_FRAMEEQ_THRESH)) {
|
||||
*exists= 1;
|
||||
return (arraylen - 1);
|
||||
}
|
||||
else if (frame > framenum)
|
||||
return arraylen;
|
||||
}
|
||||
|
||||
|
||||
/* most of the time, this loop is just to find where to put it
|
||||
* - 'loopbreaker' is just here to prevent infinite loops
|
||||
*/
|
||||
for (loopbreaker=0; (start <= end) && (loopbreaker < maxloop); loopbreaker++) {
|
||||
/* compute and get midpoint */
|
||||
int mid = start + ((end - start) / 2); /* we calculate the midpoint this way to avoid int overflows... */
|
||||
float midfra= array[mid].time;
|
||||
|
||||
/* check if exactly equal to midpoint */
|
||||
if (IS_EQT(frame, midfra, BINARYSEARCH_FRAMEEQ_THRESH)) {
|
||||
*exists = 1;
|
||||
return mid;
|
||||
}
|
||||
|
||||
/* repeat in upper/lower half */
|
||||
if (frame > midfra)
|
||||
start= mid + 1;
|
||||
else if (frame < midfra)
|
||||
end= mid - 1;
|
||||
}
|
||||
|
||||
/* print error if loop-limit exceeded */
|
||||
if (loopbreaker == (maxloop-1)) {
|
||||
printf("Error: binarysearch_fcm_envelopedata_index() was taking too long \n");
|
||||
|
||||
// include debug info
|
||||
printf("\tround = %d: start = %d, end = %d, arraylen = %d \n", loopbreaker, start, end, arraylen);
|
||||
}
|
||||
|
||||
/* not found, so return where to place it */
|
||||
return start;
|
||||
}
|
||||
|
||||
/* callback to add new envelope data point */
|
||||
// TODO: should we have a separate file for things like this?
|
||||
static void fmod_envelope_addpoint_cb (bContext *C, void *fcm_dv, void *dummy)
|
||||
{
|
||||
Scene *scene= CTX_data_scene(C);
|
||||
FMod_Envelope *env= (FMod_Envelope *)fcm_dv;
|
||||
FCM_EnvelopeData *fedn;
|
||||
FCM_EnvelopeData fed;
|
||||
|
||||
/* init template data */
|
||||
fed.min= -1.0f;
|
||||
fed.max= 1.0f;
|
||||
fed.time= (float)scene->r.cfra; // XXX make this int for ease of use?
|
||||
fed.f1= fed.f2= 0;
|
||||
|
||||
/* check that no data exists for the current frame... */
|
||||
if (env->data) {
|
||||
short exists = -1;
|
||||
int i= binarysearch_fcm_envelopedata_index(env->data, (float)(scene->r.cfra), env->totvert, &exists);
|
||||
|
||||
/* binarysearch_...() will set exists by default to 0, so if it is non-zero, that means that the point exists already */
|
||||
if (exists)
|
||||
return;
|
||||
|
||||
/* add new */
|
||||
fedn= MEM_callocN((env->totvert+1)*sizeof(FCM_EnvelopeData), "FCM_EnvelopeData");
|
||||
|
||||
/* add the points that should occur before the point to be pasted */
|
||||
if (i > 0)
|
||||
memcpy(fedn, env->data, i*sizeof(FCM_EnvelopeData));
|
||||
|
||||
/* add point to paste at index i */
|
||||
*(fedn + i)= fed;
|
||||
|
||||
/* add the points that occur after the point to be pasted */
|
||||
if (i < env->totvert)
|
||||
memcpy(fedn+i+1, env->data+i, (env->totvert-i)*sizeof(FCM_EnvelopeData));
|
||||
|
||||
/* replace (+ free) old with new */
|
||||
MEM_freeN(env->data);
|
||||
env->data= fedn;
|
||||
|
||||
env->totvert++;
|
||||
}
|
||||
else {
|
||||
env->data= MEM_callocN(sizeof(FCM_EnvelopeData), "FCM_EnvelopeData");
|
||||
*(env->data)= fed;
|
||||
|
||||
env->totvert= 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* callback to remove envelope data point */
|
||||
// TODO: should we have a separate file for things like this?
|
||||
static void fmod_envelope_deletepoint_cb (bContext *C, void *fcm_dv, void *ind_v)
|
||||
{
|
||||
FMod_Envelope *env= (FMod_Envelope *)fcm_dv;
|
||||
FCM_EnvelopeData *fedn;
|
||||
int index= GET_INT_FROM_POINTER(ind_v);
|
||||
|
||||
/* check that no data exists for the current frame... */
|
||||
if (env->totvert > 1) {
|
||||
/* allocate a new smaller array */
|
||||
fedn= MEM_callocN(sizeof(FCM_EnvelopeData)*(env->totvert-1), "FCM_EnvelopeData");
|
||||
|
||||
memcpy(fedn, &env->data, sizeof(FCM_EnvelopeData)*(index));
|
||||
memcpy(&fedn[index], &env->data[index+1], sizeof(FCM_EnvelopeData)*(env->totvert-index-1));
|
||||
|
||||
/* free old array, and set the new */
|
||||
MEM_freeN(env->data);
|
||||
env->data= fedn;
|
||||
env->totvert--;
|
||||
}
|
||||
else {
|
||||
/* just free array, since the only vert was deleted */
|
||||
if (env->data)
|
||||
MEM_freeN(env->data);
|
||||
env->totvert= 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* draw settings for envelope modifier */
|
||||
static void draw_modifier__envelope(uiBlock *block, FCurve *fcu, FModifier *fcm, int *yco, short *height, short width, short active, int rb_col)
|
||||
{
|
||||
FMod_Envelope *env= (FMod_Envelope *)fcm->data;
|
||||
FCM_EnvelopeData *fed;
|
||||
uiBut *but;
|
||||
int cy= (*yco - 28);
|
||||
int i;
|
||||
|
||||
/* set the height:
|
||||
* - basic settings + variable height from envelope controls
|
||||
*/
|
||||
(*height) = 115 + (35 * env->totvert);
|
||||
|
||||
/* basic settings (backdrop + general settings + some padding) */
|
||||
DRAW_BACKDROP((*height));
|
||||
|
||||
/* General Settings */
|
||||
uiDefBut(block, LABEL, 1, "Envelope:", 10, cy, 100, 20, NULL, 0.0, 0.0, 0, 0, "Settings for cycling before first keyframe");
|
||||
cy -= 20;
|
||||
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Reference Val:", 10, cy, 300, 20, &env->midval, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "");
|
||||
cy -= 20;
|
||||
|
||||
uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Min:", 10, cy, 150, 20, &env->min, -UI_FLT_MAX, env->max, 10, 3, "Minimum value (relative to Reference Value) that is used as the 'normal' minimum value");
|
||||
uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Max:", 160, cy, 150, 20, &env->max, env->min, UI_FLT_MAX, 10, 3, "Maximum value (relative to Reference Value) that is used as the 'normal' maximum value");
|
||||
cy -= 35;
|
||||
uiBlockEndAlign(block);
|
||||
|
||||
|
||||
/* Points header */
|
||||
uiDefBut(block, LABEL, 1, "Control Points:", 10, cy, 150, 20, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
but= uiDefBut(block, BUT, B_FMODIFIER_REDRAW, "Add Point", 160,cy,150,19, NULL, 0, 0, 0, 0, "Adds a new control-point to the envelope on the current frame");
|
||||
uiButSetFunc(but, fmod_envelope_addpoint_cb, env, NULL);
|
||||
cy -= 35;
|
||||
|
||||
/* Points List */
|
||||
for (i=0, fed=env->data; i < env->totvert; i++, fed++) {
|
||||
uiBlockBeginAlign(block);
|
||||
but=uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Fra:", 2, cy, 90, 20, &fed->time, -UI_FLT_MAX, UI_FLT_MAX, 10, 1, "Frame that envelope point occurs");
|
||||
uiButSetFunc(but, validate_fmodifier_cb, fcu, fcm);
|
||||
|
||||
uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Min:", 92, cy, 100, 20, &fed->min, -UI_FLT_MAX, UI_FLT_MAX, 10, 2, "Minimum bound of envelope at this point");
|
||||
uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Max:", 192, cy, 100, 20, &fed->max, -UI_FLT_MAX, UI_FLT_MAX, 10, 2, "Maximum bound of envelope at this point");
|
||||
|
||||
but= uiDefIconBut(block, BUT, B_FMODIFIER_REDRAW, ICON_X, 292, cy, 18, 20, NULL, 0.0, 0.0, 0.0, 0.0, "Delete envelope control point");
|
||||
uiButSetFunc(but, fmod_envelope_deletepoint_cb, env, SET_INT_IN_POINTER(i));
|
||||
uiBlockBeginAlign(block);
|
||||
cy -= 25;
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------- */
|
||||
|
||||
/* draw settings for limits modifier */
|
||||
static void draw_modifier__limits(uiBlock *block, FCurve *fcu, FModifier *fcm, int *yco, short *height, short width, short active, int rb_col)
|
||||
{
|
||||
FMod_Limits *data= (FMod_Limits *)fcm->data;
|
||||
const int togButWidth = 50;
|
||||
const int textButWidth = ((width/2)-togButWidth);
|
||||
|
||||
/* set the height */
|
||||
(*height) = 60;
|
||||
|
||||
/* basic settings (backdrop + some padding) */
|
||||
DRAW_BACKDROP((*height));
|
||||
|
||||
/* Draw Pairs of LimitToggle+LimitValue */
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefButBitI(block, TOGBUT, FCM_LIMIT_XMIN, B_FMODIFIER_REDRAW, "xMin", 5, *yco-30, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum x value");
|
||||
uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 5+togButWidth, *yco-30, (textButWidth-5), 18, &data->rect.xmin, -UI_FLT_MAX, UI_FLT_MAX, 0.1,0.5,"Lowest x value to allow");
|
||||
uiBlockEndAlign(block);
|
||||
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefButBitI(block, TOGBUT, FCM_LIMIT_XMAX, B_FMODIFIER_REDRAW, "XMax", 5+(width-(textButWidth-5)-togButWidth), *yco-30, 50, 18, &data->flag, 0, 24, 0, 0, "Use maximum x value");
|
||||
uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 5+(width-textButWidth-5), *yco-30, (textButWidth-5), 18, &data->rect.xmax, -UI_FLT_MAX, UI_FLT_MAX, 0.1,0.5,"Highest x value to allow");
|
||||
uiBlockEndAlign(block);
|
||||
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefButBitI(block, TOGBUT, FCM_LIMIT_YMIN, B_FMODIFIER_REDRAW, "yMin", 5, *yco-52, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum y value");
|
||||
uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 5+togButWidth, *yco-52, (textButWidth-5), 18, &data->rect.ymin, -UI_FLT_MAX, UI_FLT_MAX, 0.1,0.5,"Lowest y value to allow");
|
||||
uiBlockEndAlign(block);
|
||||
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefButBitI(block, TOGBUT, FCM_LIMIT_YMAX, B_FMODIFIER_REDRAW, "YMax", 5+(width-(textButWidth-5)-togButWidth), *yco-52, 50, 18, &data->flag, 0, 24, 0, 0, "Use maximum y value");
|
||||
uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 5+(width-textButWidth-5), *yco-52, (textButWidth-5), 18, &data->rect.ymax, -UI_FLT_MAX, UI_FLT_MAX, 0.1,0.5,"Highest y value to allow");
|
||||
uiBlockEndAlign(block);
|
||||
}
|
||||
|
||||
/* --------------- */
|
||||
|
||||
static void graph_panel_modifier_draw(uiBlock *block, FCurve *fcu, FModifier *fcm, int *yco)
|
||||
{
|
||||
FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
|
||||
uiBut *but;
|
||||
short active= (fcm->flag & FMODIFIER_FLAG_ACTIVE);
|
||||
short width= 314;
|
||||
short height = 0;
|
||||
int rb_col;
|
||||
|
||||
/* draw header */
|
||||
{
|
||||
uiBlockSetEmboss(block, UI_EMBOSSN);
|
||||
|
||||
/* rounded header */
|
||||
rb_col= (active)?-20:20;
|
||||
but= uiDefBut(block, ROUNDBOX, B_REDR, "", 0, *yco-2, width, 24, NULL, 5.0, 0.0, 15.0, (float)(rb_col-20), "");
|
||||
|
||||
/* expand */
|
||||
uiDefIconButBitS(block, ICONTOG, FMODIFIER_FLAG_EXPANDED, B_REDR, ICON_TRIA_RIGHT, 5, *yco-1, 20, 20, &fcm->flag, 0.0, 0.0, 0, 0, "Modifier is expanded.");
|
||||
|
||||
/* checkbox for 'active' status (for now) */
|
||||
but= uiDefIconButBitS(block, ICONTOG, FMODIFIER_FLAG_ACTIVE, B_REDR, ICON_RADIOBUT_OFF, 25, *yco-1, 20, 20, &fcm->flag, 0.0, 0.0, 0, 0, "Modifier is active one.");
|
||||
uiButSetFunc(but, activate_fmodifier_cb, fcu, fcm);
|
||||
|
||||
/* name */
|
||||
if (fmi)
|
||||
uiDefBut(block, LABEL, 1, fmi->name, 10+40, *yco, 150, 20, NULL, 0.0, 0.0, 0, 0, "F-Curve Modifier Type. Click to make modifier active one.");
|
||||
else
|
||||
uiDefBut(block, LABEL, 1, "<Unknown Modifier>", 10+40, *yco, 150, 20, NULL, 0.0, 0.0, 0, 0, "F-Curve Modifier Type. Click to make modifier active one.");
|
||||
|
||||
/* 'mute' button */
|
||||
uiDefIconButBitS(block, ICONTOG, FMODIFIER_FLAG_MUTED, B_REDR, ICON_MUTE_IPO_OFF, 10+(width-60), *yco-1, 20, 20, &fcm->flag, 0.0, 0.0, 0, 0, "Modifier is temporarily muted (not evaluated).");
|
||||
|
||||
/* delete button */
|
||||
but= uiDefIconBut(block, BUT, B_REDR, ICON_X, 10+(width-30), *yco, 19, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Delete F-Curve Modifier.");
|
||||
uiButSetFunc(but, delete_fmodifier_cb, fcu, fcm);
|
||||
|
||||
uiBlockSetEmboss(block, UI_EMBOSS);
|
||||
}
|
||||
|
||||
/* when modifier is expanded, draw settings */
|
||||
if (fcm->flag & FMODIFIER_FLAG_EXPANDED) {
|
||||
/* draw settings for individual modifiers */
|
||||
switch (fcm->type) {
|
||||
case FMODIFIER_TYPE_GENERATOR: /* Generator */
|
||||
draw_modifier__generator(block, fcu, fcm, yco, &height, width, active, rb_col);
|
||||
break;
|
||||
|
||||
case FMODIFIER_TYPE_CYCLES: /* Cycles */
|
||||
draw_modifier__cycles(block, fcu, fcm, yco, &height, width, active, rb_col);
|
||||
break;
|
||||
|
||||
case FMODIFIER_TYPE_ENVELOPE: /* Envelope */
|
||||
draw_modifier__envelope(block, fcu, fcm, yco, &height, width, active, rb_col);
|
||||
break;
|
||||
|
||||
case FMODIFIER_TYPE_LIMITS: /* Limits */
|
||||
draw_modifier__limits(block, fcu, fcm, yco, &height, width, active, rb_col);
|
||||
break;
|
||||
|
||||
case FMODIFIER_TYPE_NOISE: /* Noise */
|
||||
draw_modifier__noise(block, fcu, fcm, yco, &height, width, active, rb_col);
|
||||
break;
|
||||
|
||||
default: /* unknown type */
|
||||
height= 96;
|
||||
//DRAW_BACKDROP(height); // XXX buggy...
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* adjust height for new to start */
|
||||
(*yco) -= (height + 27);
|
||||
}
|
||||
|
||||
static void graph_panel_modifiers(const bContext *C, Panel *pa)
|
||||
{
|
||||
bAnimListElem *ale;
|
||||
FCurve *fcu;
|
||||
FModifier *fcm;
|
||||
uiLayout *col, *row;
|
||||
uiBlock *block;
|
||||
int yco= 190;
|
||||
|
||||
if(!graph_panel_context(C, &ale, &fcu))
|
||||
if (!graph_panel_context(C, &ale, &fcu))
|
||||
return;
|
||||
|
||||
block= uiLayoutFreeBlock(pa->layout);
|
||||
block= uiLayoutGetBlock(pa->layout);
|
||||
uiBlockSetHandleFunc(block, do_graph_region_modifier_buttons, NULL);
|
||||
|
||||
/* 'add modifier' button at top of panel */
|
||||
// XXX for now, this will be a operator button which calls a temporary 'add modifier' operator
|
||||
uiDefButO(block, BUT, "GRAPHEDIT_OT_fmodifier_add", WM_OP_INVOKE_REGION_WIN, "Add Modifier", 10, 225, 150, 20, "Adds a new F-Curve Modifier for the active F-Curve");
|
||||
{
|
||||
row= uiLayoutRow(pa->layout, 0);
|
||||
block= uiLayoutGetBlock(row);
|
||||
|
||||
// XXX for now, this will be a operator button which calls a temporary 'add modifier' operator
|
||||
uiDefButO(block, BUT, "GRAPH_OT_fmodifier_add", WM_OP_INVOKE_REGION_WIN, "Add Modifier", 10, 0, 150, 20, "Adds a new F-Curve Modifier for the active F-Curve");
|
||||
}
|
||||
|
||||
/* draw each modifier */
|
||||
for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next)
|
||||
graph_panel_modifier_draw(block, fcu, fcm, &yco);
|
||||
for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next) {
|
||||
col= uiLayoutColumn(pa->layout, 1);
|
||||
|
||||
ANIM_uiTemplate_fmodifier_draw(col, ale->id, &fcu->modifiers, fcm);
|
||||
}
|
||||
|
||||
MEM_freeN(ale);
|
||||
}
|
||||
|
||||
/* ******************* general ******************************** */
|
||||
|
||||
/* Find 'active' F-Curve. It must be editable, since that's the purpose of these buttons (subject to change).
|
||||
* We return the 'wrapper' since it contains valuable context info (about hierarchy), which will need to be freed
|
||||
* when the caller is done with it.
|
||||
*/
|
||||
// TODO: move this to anim api with another name?
|
||||
bAnimListElem *get_active_fcurve_channel (bAnimContext *ac)
|
||||
{
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
int filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_ACTIVE | ANIMFILTER_CURVESONLY);
|
||||
int items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
|
||||
|
||||
/* We take the first F-Curve only, since some other ones may have had 'active' flag set
|
||||
* if they were from linked data.
|
||||
*/
|
||||
if (items) {
|
||||
bAnimListElem *ale= (bAnimListElem *)anim_data.first;
|
||||
|
||||
/* remove first item from list, then free the rest of the list and return the stored one */
|
||||
BLI_remlink(&anim_data, ale);
|
||||
BLI_freelistN(&anim_data);
|
||||
|
||||
return ale;
|
||||
}
|
||||
|
||||
/* no active F-Curve */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void graph_buttons_register(ARegionType *art)
|
||||
{
|
||||
PanelType *pt;
|
||||
@@ -1066,10 +437,10 @@ static int graph_properties(bContext *C, wmOperator *op)
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void GRAPHEDIT_OT_properties(wmOperatorType *ot)
|
||||
void GRAPH_OT_properties(wmOperatorType *ot)
|
||||
{
|
||||
ot->name= "Properties";
|
||||
ot->idname= "GRAPHEDIT_OT_properties";
|
||||
ot->idname= "GRAPH_OT_properties";
|
||||
|
||||
ot->exec= graph_properties;
|
||||
ot->poll= ED_operator_ipo_active; // xxx
|
||||
|
||||
@@ -835,12 +835,12 @@ void graph_draw_curves (bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGri
|
||||
*/
|
||||
for (ale=anim_data.first; ale; ale=ale->next) {
|
||||
FCurve *fcu= (FCurve *)ale->key_data;
|
||||
FModifier *fcm= fcurve_find_active_modifier(fcu);
|
||||
//Object *nob= ANIM_nla_mapping_get(ac, ale);
|
||||
FModifier *fcm= find_active_fmodifier(&fcu->modifiers);
|
||||
AnimData *adt= ANIM_nla_mapping_get(ac, ale);
|
||||
|
||||
/* map keyframes for drawing if scaled F-Curve */
|
||||
//if (nob)
|
||||
// ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 0, 0);
|
||||
if (adt)
|
||||
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0);
|
||||
|
||||
/* draw curve:
|
||||
* - curve line may be result of one or more destructive modifiers or just the raw data,
|
||||
@@ -918,8 +918,8 @@ void graph_draw_curves (bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGri
|
||||
}
|
||||
|
||||
/* undo mapping of keyframes for drawing if scaled F-Curve */
|
||||
//if (nob)
|
||||
// ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 1, 0);
|
||||
if (adt)
|
||||
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 0);
|
||||
}
|
||||
|
||||
/* free list of curves */
|
||||
@@ -1206,6 +1206,17 @@ void graph_draw_channel_names(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar)
|
||||
expand = ICON_TRIA_RIGHT;
|
||||
}
|
||||
|
||||
/* for now, 'special' (i.e. in front of name) is used to show visibility status */
|
||||
if (agrp->flag & AGRP_NOTVISIBLE)
|
||||
special= ICON_CHECKBOX_DEHLT;
|
||||
else
|
||||
special= ICON_CHECKBOX_HLT;
|
||||
|
||||
if (agrp->flag & AGRP_MUTED)
|
||||
mute = ICON_MUTE_IPO_ON;
|
||||
else
|
||||
mute = ICON_MUTE_IPO_OFF;
|
||||
|
||||
if (EDITABLE_AGRP(agrp))
|
||||
protect = ICON_UNLOCKED;
|
||||
else
|
||||
|
||||
@@ -67,11 +67,13 @@
|
||||
#include "BKE_fcurve.h"
|
||||
#include "BKE_key.h"
|
||||
#include "BKE_material.h"
|
||||
#include "BKE_nla.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_report.h"
|
||||
#include "BKE_utildefines.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
#include "UI_view2d.h"
|
||||
|
||||
#include "ED_anim_api.h"
|
||||
@@ -114,16 +116,16 @@ void get_graph_keyframe_extents (bAnimContext *ac, float *xmin, float *xmax, flo
|
||||
if (anim_data.first) {
|
||||
/* go through channels, finding max extents */
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
Object *nob= NULL; //ANIM_nla_mapping_get(ac, ale);
|
||||
AnimData *adt= ANIM_nla_mapping_get(ac, ale);
|
||||
FCurve *fcu= (FCurve *)ale->key_data;
|
||||
float txmin, txmax, tymin, tymax;
|
||||
|
||||
/* get range and apply necessary scaling before */
|
||||
calc_fcurve_bounds(fcu, &txmin, &txmax, &tymin, &tymax);
|
||||
|
||||
if (nob) {
|
||||
txmin= get_action_frame_inv(nob, txmin);
|
||||
txmax= get_action_frame_inv(nob, txmax);
|
||||
if (adt) {
|
||||
txmin= BKE_nla_tweakedit_remap(adt, txmin, NLATIME_CONVERT_MAP);
|
||||
txmax= BKE_nla_tweakedit_remap(adt, txmax, NLATIME_CONVERT_MAP);
|
||||
}
|
||||
|
||||
/* try to set cur using these values, if they're more extreme than previously set values */
|
||||
@@ -180,15 +182,15 @@ static int graphkeys_previewrange_exec(bContext *C, wmOperator *op)
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void GRAPHEDIT_OT_previewrange_set (wmOperatorType *ot)
|
||||
void GRAPH_OT_previewrange_set (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Auto-Set Preview Range";
|
||||
ot->idname= "GRAPHEDIT_OT_previewrange_set";
|
||||
ot->idname= "GRAPH_OT_previewrange_set";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= graphkeys_previewrange_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= graphop_visible_keyframes_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -227,15 +229,15 @@ static int graphkeys_viewall_exec(bContext *C, wmOperator *op)
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void GRAPHEDIT_OT_view_all (wmOperatorType *ot)
|
||||
void GRAPH_OT_view_all (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "View All";
|
||||
ot->idname= "GRAPHEDIT_OT_view_all";
|
||||
ot->idname= "GRAPH_OT_view_all";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= graphkeys_viewall_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= graphop_visible_keyframes_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -271,6 +273,7 @@ static void create_ghost_curves (bAnimContext *ac, int start, int end)
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
FCurve *fcu= (FCurve *)ale->key_data;
|
||||
FCurve *gcu= MEM_callocN(sizeof(FCurve), "Ghost FCurve");
|
||||
AnimData *adt= ANIM_nla_mapping_get(ac, ale);
|
||||
ChannelDriver *driver= fcu->driver;
|
||||
FPoint *fpt;
|
||||
int cfra;
|
||||
@@ -286,8 +289,10 @@ static void create_ghost_curves (bAnimContext *ac, int start, int end)
|
||||
|
||||
/* use the sampling callback at 1-frame intervals from start to end frames */
|
||||
for (cfra= start; cfra <= end; cfra++, fpt++) {
|
||||
fpt->vec[0]= (float)cfra;
|
||||
fpt->vec[1]= fcurve_samplingcb_evalcurve(fcu, NULL, (float)cfra);
|
||||
float cfrae= BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP);
|
||||
|
||||
fpt->vec[0]= cfrae;
|
||||
fpt->vec[1]= fcurve_samplingcb_evalcurve(fcu, NULL, cfrae);
|
||||
}
|
||||
|
||||
/* set color of ghost curve
|
||||
@@ -334,16 +339,16 @@ static int graphkeys_create_ghostcurves_exec(bContext *C, wmOperator *op)
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void GRAPHEDIT_OT_ghost_curves_create (wmOperatorType *ot)
|
||||
void GRAPH_OT_ghost_curves_create (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Create Ghost Curves";
|
||||
ot->idname= "GRAPHEDIT_OT_ghost_curves_create";
|
||||
ot->idname= "GRAPH_OT_ghost_curves_create";
|
||||
ot->description= "Create snapshot (Ghosts) of selected F-Curves as background aid for active Graph Editor.";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= graphkeys_create_ghostcurves_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= graphop_visible_keyframes_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -377,16 +382,16 @@ static int graphkeys_clear_ghostcurves_exec(bContext *C, wmOperator *op)
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void GRAPHEDIT_OT_ghost_curves_clear (wmOperatorType *ot)
|
||||
void GRAPH_OT_ghost_curves_clear (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Create Ghost Curves";
|
||||
ot->idname= "GRAPHEDIT_OT_ghost_curves_clear";
|
||||
ot->idname= "GRAPH_OT_ghost_curves_clear";
|
||||
ot->description= "Clear F-Curve snapshots (Ghosts) for active Graph Editor.";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= graphkeys_clear_ghostcurves_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= ED_operator_ipo_active;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -395,7 +400,103 @@ void GRAPHEDIT_OT_ghost_curves_clear (wmOperatorType *ot)
|
||||
/* ************************************************************************** */
|
||||
/* GENERAL STUFF */
|
||||
|
||||
// TODO: insertkey
|
||||
/* ******************** Insert Keyframes Operator ************************* */
|
||||
|
||||
/* defines for insert keyframes tool */
|
||||
EnumPropertyItem prop_graphkeys_insertkey_types[] = {
|
||||
{1, "ALL", 0, "All Channels", ""},
|
||||
{2, "SEL", 0, "Only Selected Channels", ""},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
/* this function is responsible for snapping keyframes to frame-times */
|
||||
static void insert_graph_keys(bAnimContext *ac, short mode)
|
||||
{
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
bAnimListElem *ale;
|
||||
int filter;
|
||||
|
||||
Scene *scene= ac->scene;
|
||||
float cfra= (float)CFRA;
|
||||
short flag = 0;
|
||||
|
||||
/* filter data */
|
||||
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
|
||||
if (mode == 2) filter |= ANIMFILTER_SEL;
|
||||
|
||||
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
|
||||
|
||||
/* init keyframing flag */
|
||||
if (IS_AUTOKEY_FLAG(AUTOMATKEY)) flag |= INSERTKEY_MATRIX;
|
||||
if (IS_AUTOKEY_FLAG(INSERTNEEDED)) flag |= INSERTKEY_NEEDED;
|
||||
// if (IS_AUTOKEY_MODE(EDITKEYS)) flag |= INSERTKEY_REPLACE;
|
||||
|
||||
/* insert keyframes */
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
AnimData *adt= ANIM_nla_mapping_get(ac, ale);
|
||||
FCurve *fcu= (FCurve *)ale->key_data;
|
||||
|
||||
/* adjust current frame for NLA-mapping */
|
||||
if (adt)
|
||||
cfra= BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
|
||||
else
|
||||
cfra= (float)CFRA;
|
||||
|
||||
/* if there's an id */
|
||||
if (ale->id)
|
||||
insert_keyframe(ale->id, NULL, ((fcu->grp)?(fcu->grp->name):(NULL)), fcu->rna_path, fcu->array_index, cfra, flag);
|
||||
else
|
||||
insert_vert_fcurve(fcu, cfra, fcu->curval, 0);
|
||||
}
|
||||
|
||||
BLI_freelistN(&anim_data);
|
||||
}
|
||||
|
||||
/* ------------------- */
|
||||
|
||||
static int graphkeys_insertkey_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
bAnimContext ac;
|
||||
short mode;
|
||||
|
||||
/* get editor data */
|
||||
if (ANIM_animdata_get_context(C, &ac) == 0)
|
||||
return OPERATOR_CANCELLED;
|
||||
if (ac.datatype == ANIMCONT_GPENCIL)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
/* which channels to affect? */
|
||||
mode= RNA_enum_get(op->ptr, "type");
|
||||
|
||||
/* insert keyframes */
|
||||
insert_graph_keys(&ac, mode);
|
||||
|
||||
/* validate keyframes after editing */
|
||||
ANIM_editkeyframes_refresh(&ac);
|
||||
|
||||
/* set notifier that keyframes have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void GRAPH_OT_insert_keyframe (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Insert Keyframes";
|
||||
ot->idname= "GRAPH_OT_insert_keyframe";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke= WM_menu_invoke;
|
||||
ot->exec= graphkeys_insertkey_exec;
|
||||
ot->poll= graphop_editable_keyframes_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
|
||||
/* id-props */
|
||||
RNA_def_enum(ot->srna, "type", prop_graphkeys_insertkey_types, 0, "Type", "");
|
||||
}
|
||||
|
||||
/* ******************** Click-Insert Keyframes Operator ************************* */
|
||||
|
||||
@@ -403,6 +504,7 @@ static int graphkeys_click_insert_exec (bContext *C, wmOperator *op)
|
||||
{
|
||||
bAnimContext ac;
|
||||
bAnimListElem *ale;
|
||||
AnimData *adt;
|
||||
float frame, val;
|
||||
|
||||
/* get animation context */
|
||||
@@ -420,14 +522,18 @@ static int graphkeys_click_insert_exec (bContext *C, wmOperator *op)
|
||||
frame= RNA_float_get(op->ptr, "frame");
|
||||
val= RNA_float_get(op->ptr, "value");
|
||||
|
||||
/* apply inverse NLA-mapping to frame to get correct time in un-scaled action */
|
||||
adt= ANIM_nla_mapping_get(&ac, ale);
|
||||
frame= BKE_nla_tweakedit_remap(adt, frame, NLATIME_CONVERT_UNMAP);
|
||||
|
||||
/* insert keyframe on the specified frame + value */
|
||||
insert_vert_fcurve((FCurve *)ale->data, frame, val, 0);
|
||||
|
||||
/* free temp data */
|
||||
MEM_freeN(ale);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
|
||||
/* set notifier that keyframes have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
|
||||
|
||||
/* done */
|
||||
return OPERATOR_FINISHED;
|
||||
@@ -461,16 +567,16 @@ static int graphkeys_click_insert_invoke (bContext *C, wmOperator *op, wmEvent *
|
||||
return graphkeys_click_insert_exec(C, op);
|
||||
}
|
||||
|
||||
void GRAPHEDIT_OT_keyframes_click_insert (wmOperatorType *ot)
|
||||
void GRAPH_OT_click_insert (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Click-Insert Keyframes";
|
||||
ot->idname= "GRAPHEDIT_OT_keyframes_click_insert";
|
||||
ot->idname= "GRAPH_OT_click_insert";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke= graphkeys_click_insert_invoke;
|
||||
ot->exec= graphkeys_click_insert_exec;
|
||||
ot->poll= ED_operator_areaactive; // XXX active + editable poll
|
||||
ot->poll= graphop_active_fcurve_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -538,21 +644,19 @@ static int graphkeys_copy_exec(bContext *C, wmOperator *op)
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
/* set notifier that things have changed */
|
||||
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
|
||||
|
||||
/* just return - no operator needed here (no changes) */
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void GRAPHEDIT_OT_keyframes_copy (wmOperatorType *ot)
|
||||
void GRAPH_OT_copy (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Copy Keyframes";
|
||||
ot->idname= "GRAPHEDIT_OT_keyframes_copy";
|
||||
ot->idname= "GRAPH_OT_copy";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= graphkeys_copy_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= graphop_editable_keyframes_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -577,21 +681,21 @@ static int graphkeys_paste_exec(bContext *C, wmOperator *op)
|
||||
/* validate keyframes after editing */
|
||||
ANIM_editkeyframes_refresh(&ac);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
|
||||
/* set notifier that keyframes have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void GRAPHEDIT_OT_keyframes_paste (wmOperatorType *ot)
|
||||
void GRAPH_OT_paste (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Paste Keyframes";
|
||||
ot->idname= "GRAPHEDIT_OT_keyframes_paste";
|
||||
ot->idname= "GRAPH_OT_paste";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= graphkeys_paste_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= graphop_editable_keyframes_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -634,8 +738,8 @@ static int graphkeys_duplicate_exec(bContext *C, wmOperator *op)
|
||||
/* validate keyframes after editing */
|
||||
ANIM_editkeyframes_refresh(&ac);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
|
||||
/* set notifier that keyframes have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
@@ -650,16 +754,16 @@ static int graphkeys_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *even
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void GRAPHEDIT_OT_keyframes_duplicate (wmOperatorType *ot)
|
||||
void GRAPH_OT_duplicate (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Duplicate Keyframes";
|
||||
ot->idname= "GRAPHEDIT_OT_keyframes_duplicate";
|
||||
ot->idname= "GRAPH_OT_duplicate";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke= graphkeys_duplicate_invoke;
|
||||
ot->exec= graphkeys_duplicate_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= graphop_editable_keyframes_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -705,22 +809,22 @@ static int graphkeys_delete_exec(bContext *C, wmOperator *op)
|
||||
/* validate keyframes after editing */
|
||||
ANIM_editkeyframes_refresh(&ac);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
|
||||
/* set notifier that keyframes have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void GRAPHEDIT_OT_keyframes_delete (wmOperatorType *ot)
|
||||
void GRAPH_OT_delete (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Delete Keyframes";
|
||||
ot->idname= "GRAPHEDIT_OT_keyframes_delete";
|
||||
ot->idname= "GRAPH_OT_delete";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke= WM_operator_confirm;
|
||||
ot->exec= graphkeys_delete_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= graphop_editable_keyframes_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -766,22 +870,22 @@ static int graphkeys_clean_exec(bContext *C, wmOperator *op)
|
||||
/* validate keyframes after editing */
|
||||
ANIM_editkeyframes_refresh(&ac);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
|
||||
/* set notifier that keyframes have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void GRAPHEDIT_OT_keyframes_clean (wmOperatorType *ot)
|
||||
void GRAPH_OT_clean (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Clean Keyframes";
|
||||
ot->idname= "GRAPHEDIT_OT_keyframes_clean";
|
||||
ot->idname= "GRAPH_OT_clean";
|
||||
|
||||
/* api callbacks */
|
||||
//ot->invoke= // XXX we need that number popup for this!
|
||||
ot->exec= graphkeys_clean_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= graphop_editable_keyframes_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -847,22 +951,23 @@ static int graphkeys_bake_exec(bContext *C, wmOperator *op)
|
||||
/* validate keyframes after editing */
|
||||
ANIM_editkeyframes_refresh(&ac);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
|
||||
/* set notifier that keyframes have changed */
|
||||
// NOTE: some distinction between order/number of keyframes and type should be made?
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void GRAPHEDIT_OT_keyframes_bake (wmOperatorType *ot)
|
||||
void GRAPH_OT_bake (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Bake Curve";
|
||||
ot->idname= "GRAPHEDIT_OT_keyframes_bake";
|
||||
ot->idname= "GRAPH_OT_bake";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke= WM_operator_confirm; // FIXME...
|
||||
ot->exec= graphkeys_bake_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= graphop_editable_keyframes_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -973,21 +1078,21 @@ static int graphkeys_sample_exec(bContext *C, wmOperator *op)
|
||||
/* validate keyframes after editing */
|
||||
ANIM_editkeyframes_refresh(&ac);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
|
||||
/* set notifier that keyframes have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void GRAPHEDIT_OT_keyframes_sample (wmOperatorType *ot)
|
||||
void GRAPH_OT_sample (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Sample Keyframes";
|
||||
ot->idname= "GRAPHEDIT_OT_keyframes_sample";
|
||||
ot->idname= "GRAPH_OT_sample";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= graphkeys_sample_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= graphop_editable_keyframes_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -1047,22 +1152,22 @@ static int graphkeys_expo_exec(bContext *C, wmOperator *op)
|
||||
/* validate keyframes after editing */
|
||||
ANIM_editkeyframes_refresh(&ac);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
|
||||
/* set notifier that keyframe properties have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_PROP, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void GRAPHEDIT_OT_keyframes_extrapolation_type (wmOperatorType *ot)
|
||||
void GRAPH_OT_extrapolation_type (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Set Keyframe Extrapolation";
|
||||
ot->idname= "GRAPHEDIT_OT_keyframes_extrapolation_type";
|
||||
ot->idname= "GRAPH_OT_extrapolation_type";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke= WM_menu_invoke;
|
||||
ot->exec= graphkeys_expo_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= graphop_editable_keyframes_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -1115,22 +1220,22 @@ static int graphkeys_ipo_exec(bContext *C, wmOperator *op)
|
||||
/* validate keyframes after editing */
|
||||
ANIM_editkeyframes_refresh(&ac);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
|
||||
/* set notifier that keyframe properties have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_PROP, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void GRAPHEDIT_OT_keyframes_interpolation_type (wmOperatorType *ot)
|
||||
void GRAPH_OT_interpolation_type (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Set Keyframe Interpolation";
|
||||
ot->idname= "GRAPHEDIT_OT_keyframes_interpolation_type";
|
||||
ot->idname= "GRAPH_OT_interpolation_type";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke= WM_menu_invoke;
|
||||
ot->exec= graphkeys_ipo_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= graphop_editable_keyframes_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -1203,21 +1308,21 @@ static int graphkeys_handletype_exec(bContext *C, wmOperator *op)
|
||||
ANIM_editkeyframes_refresh(&ac);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_PROP, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void GRAPHEDIT_OT_keyframes_handletype (wmOperatorType *ot)
|
||||
void GRAPH_OT_handletype (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Set Keyframe Handle Type";
|
||||
ot->idname= "GRAPHEDIT_OT_keyframes_handletype";
|
||||
ot->idname= "GRAPH_OT_handletype";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke= WM_menu_invoke;
|
||||
ot->exec= graphkeys_handletype_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= graphop_editable_keyframes_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -1298,15 +1403,15 @@ static int graphkeys_euler_filter_exec (bContext *C, wmOperator *op)
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
void GRAPHEDIT_OT_keyframes_euler_filter (wmOperatorType *ot)
|
||||
void GRAPH_OT_euler_filter (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Euler Filter";
|
||||
ot->idname= "GRAPHEDIT_OT_keyframes_euler_filter";
|
||||
ot->idname= "GRAPH_OT_euler_filter";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= graphkeys_euler_filter_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= graphop_editable_keyframes_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -1314,10 +1419,10 @@ void GRAPHEDIT_OT_keyframes_euler_filter (wmOperatorType *ot)
|
||||
|
||||
#endif // XXX this is not ready for the primetime yet
|
||||
|
||||
/* ***************** Snap Current Frame Operator *********************** */
|
||||
/* ***************** Jump to Selected Frames Operator *********************** */
|
||||
|
||||
/* snap current-frame indicator to 'average time' of selected keyframe */
|
||||
static int graphkeys_cfrasnap_exec(bContext *C, wmOperator *op)
|
||||
static int graphkeys_framejump_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
bAnimContext ac;
|
||||
ListBase anim_data= {NULL, NULL};
|
||||
@@ -1333,11 +1438,21 @@ static int graphkeys_cfrasnap_exec(bContext *C, wmOperator *op)
|
||||
memset(&bed, 0, sizeof(BeztEditData));
|
||||
|
||||
/* loop over action data, averaging values */
|
||||
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE| ANIMFILTER_CURVESONLY);
|
||||
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_CURVESONLY);
|
||||
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
|
||||
|
||||
for (ale= anim_data.first; ale; ale= ale->next)
|
||||
ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, bezt_calc_average, NULL);
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
AnimData *adt= ANIM_nla_mapping_get(&ac, ale);
|
||||
|
||||
if (adt) {
|
||||
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
|
||||
ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, bezt_calc_average, NULL);
|
||||
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
|
||||
}
|
||||
else
|
||||
ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, bezt_calc_average, NULL);
|
||||
|
||||
}
|
||||
|
||||
BLI_freelistN(&anim_data);
|
||||
|
||||
@@ -1353,15 +1468,15 @@ static int graphkeys_cfrasnap_exec(bContext *C, wmOperator *op)
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void GRAPHEDIT_OT_keyframes_cfrasnap (wmOperatorType *ot)
|
||||
void GRAPH_OT_frame_jump (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Snap Current Frame to Keys";
|
||||
ot->idname= "GRAPHEDIT_OT_keyframes_cfrasnap";
|
||||
ot->name= "Jump to Frame";
|
||||
ot->idname= "GRAPH_OT_frame_jump";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= graphkeys_cfrasnap_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->exec= graphkeys_framejump_exec;
|
||||
ot->poll= graphop_visible_keyframes_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -1405,12 +1520,12 @@ static void snap_graph_keys(bAnimContext *ac, short mode)
|
||||
|
||||
/* snap keyframes */
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
Object *nob= ANIM_nla_mapping_get(ac, ale);
|
||||
AnimData *adt= ANIM_nla_mapping_get(ac, ale);
|
||||
|
||||
if (nob) {
|
||||
ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 0, 1);
|
||||
if (adt) {
|
||||
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
|
||||
ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, edit_cb, calchandles_fcurve);
|
||||
ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 1, 1);
|
||||
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
|
||||
}
|
||||
else
|
||||
ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, edit_cb, calchandles_fcurve);
|
||||
@@ -1438,22 +1553,22 @@ static int graphkeys_snap_exec(bContext *C, wmOperator *op)
|
||||
/* validate keyframes after editing */
|
||||
ANIM_editkeyframes_refresh(&ac);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
|
||||
/* set notifier that keyframes have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void GRAPHEDIT_OT_keyframes_snap (wmOperatorType *ot)
|
||||
void GRAPH_OT_snap (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Snap Keys";
|
||||
ot->idname= "GRAPHEDIT_OT_keyframes_snap";
|
||||
ot->idname= "GRAPH_OT_snap";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke= WM_menu_invoke;
|
||||
ot->exec= graphkeys_snap_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= graphop_editable_keyframes_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -1466,10 +1581,10 @@ void GRAPHEDIT_OT_keyframes_snap (wmOperatorType *ot)
|
||||
|
||||
/* defines for mirror keyframes tool */
|
||||
EnumPropertyItem prop_graphkeys_mirror_types[] = {
|
||||
{GRAPHKEYS_MIRROR_CFRA, "CFRA", 0, "Current frame", ""},
|
||||
{GRAPHKEYS_MIRROR_YAXIS, "YAXIS", 0, "Vertical Axis", ""},
|
||||
{GRAPHKEYS_MIRROR_XAXIS, "XAXIS", 0, "Horizontal Axis", ""},
|
||||
{GRAPHKEYS_MIRROR_MARKER, "MARKER", 0, "First Selected Marker", ""},
|
||||
{GRAPHKEYS_MIRROR_CFRA, "CFRA", 0, "By Times over Current frame", ""},
|
||||
{GRAPHKEYS_MIRROR_YAXIS, "YAXIS", 0, "By Times over Time=0", ""},
|
||||
{GRAPHKEYS_MIRROR_XAXIS, "XAXIS", 0, "By Values over Value=0", ""},
|
||||
{GRAPHKEYS_MIRROR_MARKER, "MARKER", 0, "By Times over First Selected Marker", ""},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
@@ -1516,12 +1631,12 @@ static void mirror_graph_keys(bAnimContext *ac, short mode)
|
||||
|
||||
/* mirror keyframes */
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
Object *nob= ANIM_nla_mapping_get(ac, ale);
|
||||
AnimData *adt= ANIM_nla_mapping_get(ac, ale);
|
||||
|
||||
if (nob) {
|
||||
ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 0, 1);
|
||||
if (adt) {
|
||||
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
|
||||
ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, edit_cb, calchandles_fcurve);
|
||||
ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 1, 1);
|
||||
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
|
||||
}
|
||||
else
|
||||
ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, edit_cb, calchandles_fcurve);
|
||||
@@ -1549,22 +1664,22 @@ static int graphkeys_mirror_exec(bContext *C, wmOperator *op)
|
||||
/* validate keyframes after editing */
|
||||
ANIM_editkeyframes_refresh(&ac);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
|
||||
/* set notifier that keyframes have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void GRAPHEDIT_OT_keyframes_mirror (wmOperatorType *ot)
|
||||
void GRAPH_OT_mirror (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Mirror Keys";
|
||||
ot->idname= "GRAPHEDIT_OT_keyframes_mirror";
|
||||
ot->idname= "GRAPH_OT_mirror";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke= WM_menu_invoke;
|
||||
ot->exec= graphkeys_mirror_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= graphop_editable_keyframes_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -1603,21 +1718,21 @@ static int graphkeys_smooth_exec(bContext *C, wmOperator *op)
|
||||
/* validate keyframes after editing */
|
||||
ANIM_editkeyframes_refresh(&ac);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
|
||||
/* set notifier that keyframes have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void GRAPHEDIT_OT_keyframes_smooth (wmOperatorType *ot)
|
||||
void GRAPH_OT_smooth (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Smooth Keys";
|
||||
ot->idname= "GRAPHEDIT_OT_keyframes_smooth";
|
||||
ot->idname= "GRAPH_OT_smooth";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= graphkeys_smooth_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= graphop_editable_keyframes_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -1626,7 +1741,35 @@ void GRAPHEDIT_OT_keyframes_smooth (wmOperatorType *ot)
|
||||
/* ************************************************************************** */
|
||||
/* F-CURVE MODIFIERS */
|
||||
|
||||
/* ******************** Add F-Curve Modifier Operator *********************** */
|
||||
/* ******************** Add F-Modifier Operator *********************** */
|
||||
|
||||
/* present a special customised popup menu for this, with some filtering */
|
||||
static int graph_fmodifier_add_invoke (bContext *C, wmOperator *op, wmEvent *event)
|
||||
{
|
||||
uiPopupMenu *pup;
|
||||
uiLayout *layout;
|
||||
int i;
|
||||
|
||||
pup= uiPupMenuBegin(C, "Add F-Curve Modifier", 0);
|
||||
layout= uiPupMenuLayout(pup);
|
||||
|
||||
/* start from 1 to skip the 'Invalid' modifier type */
|
||||
for (i = 1; i < FMODIFIER_NUM_TYPES; i++) {
|
||||
FModifierTypeInfo *fmi= get_fmodifier_typeinfo(i);
|
||||
|
||||
/* check if modifier is valid for this context */
|
||||
if (fmi == NULL)
|
||||
continue;
|
||||
|
||||
/* add entry to add this type of modifier */
|
||||
uiItemEnumO(layout, fmi->name, 0, "GRAPH_OT_fmodifier_add", "type", i);
|
||||
}
|
||||
uiItemS(layout);
|
||||
|
||||
uiPupMenuEnd(C, pup);
|
||||
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
static int graph_fmodifier_add_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
@@ -1654,9 +1797,9 @@ static int graph_fmodifier_add_exec(bContext *C, wmOperator *op)
|
||||
type= RNA_enum_get(op->ptr, "type");
|
||||
|
||||
/* add F-Modifier of specified type to active F-Curve, and make it the active one */
|
||||
fcm= fcurve_add_modifier(fcu, type);
|
||||
fcm= add_fmodifier(&fcu->modifiers, type);
|
||||
if (fcm)
|
||||
fcurve_set_active_modifier(fcu, fcm);
|
||||
set_active_fmodifier(&fcu->modifiers, fcm);
|
||||
else {
|
||||
BKE_report(op->reports, RPT_ERROR, "Modifier couldn't be added. See console for details.");
|
||||
return OPERATOR_CANCELLED;
|
||||
@@ -1666,21 +1809,22 @@ static int graph_fmodifier_add_exec(bContext *C, wmOperator *op)
|
||||
ANIM_editkeyframes_refresh(&ac);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH);
|
||||
// FIXME: this really isn't the best description for it...
|
||||
WM_event_add_notifier(C, NC_ANIMATION, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void GRAPHEDIT_OT_fmodifier_add (wmOperatorType *ot)
|
||||
void GRAPH_OT_fmodifier_add (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Add F-Curve Modifier";
|
||||
ot->idname= "GRAPHEDIT_OT_fmodifier_add";
|
||||
ot->idname= "GRAPH_OT_fmodifier_add";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke= WM_menu_invoke;
|
||||
ot->invoke= graph_fmodifier_add_invoke;
|
||||
ot->exec= graph_fmodifier_add_exec;
|
||||
ot->poll= ED_operator_areaactive; // XXX need active F-Curve
|
||||
ot->poll= graphop_active_fcurve_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
|
||||
@@ -43,10 +43,13 @@
|
||||
#include "BKE_screen.h"
|
||||
|
||||
#include "ED_anim_api.h"
|
||||
#include "ED_transform.h"
|
||||
#include "ED_screen.h"
|
||||
#include "ED_types.h"
|
||||
#include "ED_util.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
|
||||
@@ -62,76 +65,173 @@
|
||||
/* ********************************************************* */
|
||||
/* Menu Defines... */
|
||||
|
||||
/* button events */
|
||||
static void graph_viewmenu(bContext *C, uiLayout *layout, void *arg_unused)
|
||||
{
|
||||
bScreen *sc= CTX_wm_screen(C);
|
||||
ScrArea *sa= CTX_wm_area(C);
|
||||
SpaceIpo *sipo= (SpaceIpo*)CTX_wm_space_data(C);
|
||||
PointerRNA spaceptr;
|
||||
|
||||
/* retrieve state */
|
||||
RNA_pointer_create(&sc->id, &RNA_SpaceGraphEditor, sipo, &spaceptr);
|
||||
|
||||
/* create menu */
|
||||
uiItemO(layout, NULL, ICON_MENU_PANEL, "GRAPH_OT_properties");
|
||||
|
||||
uiItemS(layout);
|
||||
|
||||
uiItemR(layout, NULL, 0, &spaceptr, "show_cframe_indicator", 0, 0, 0);
|
||||
|
||||
if (sipo->flag & SIPO_NOHANDLES)
|
||||
uiItemO(layout, "Show Handles", ICON_CHECKBOX_DEHLT, "GRAPH_OT_handles_view_toggle");
|
||||
else
|
||||
uiItemO(layout, "Show Handles", ICON_CHECKBOX_HLT, "GRAPH_OT_handles_view_toggle");
|
||||
|
||||
uiItemR(layout, NULL, 0, &spaceptr, "automerge_keyframes", 0, 0, 0);
|
||||
|
||||
if (sipo->flag & SIPO_DRAWTIME)
|
||||
uiItemO(layout, "Show Frames", 0, "ANIM_OT_time_toggle");
|
||||
else
|
||||
uiItemO(layout, "Show Seconds", 0, "ANIM_OT_time_toggle");
|
||||
|
||||
uiItemS(layout);
|
||||
|
||||
uiItemO(layout, NULL, 0, "ANIM_OT_previewrange_set");
|
||||
uiItemO(layout, NULL, 0, "ANIM_OT_previewrange_clear");
|
||||
|
||||
uiItemO(layout, NULL, 0, "GRAPH_OT_previewrange_set");
|
||||
|
||||
uiItemS(layout);
|
||||
|
||||
uiItemO(layout, NULL, 0, "GRAPH_OT_frame_jump");
|
||||
|
||||
uiItemO(layout, NULL, 0, "GRAPH_OT_view_all");
|
||||
|
||||
if (sa->full)
|
||||
uiItemO(layout, NULL, 0, "SCREEN_OT_screen_full_area"); // "Tile Window", Ctrl UpArrow
|
||||
else
|
||||
uiItemO(layout, NULL, 0, "SCREEN_OT_screen_full_area"); // "Maximize Window", Ctrl DownArrow
|
||||
}
|
||||
|
||||
static void graph_selectmenu(bContext *C, uiLayout *layout, void *arg_unused)
|
||||
{
|
||||
uiItemO(layout, NULL, 0, "GRAPH_OT_select_all_toggle");
|
||||
uiItemBooleanO(layout, "Invert All", 0, "GRAPH_OT_select_all_toggle", "invert", 1);
|
||||
|
||||
uiItemS(layout);
|
||||
|
||||
uiItemO(layout, NULL, 0, "GRAPH_OT_select_border");
|
||||
uiItemBooleanO(layout, "Border Axis Range", 0, "GRAPH_OT_select_border", "axis_range", 1);
|
||||
|
||||
uiItemS(layout);
|
||||
|
||||
uiItemEnumO(layout, "Columns on Selected Keys", 0, "GRAPH_OT_select_column", "mode", GRAPHKEYS_COLUMNSEL_KEYS);
|
||||
uiItemEnumO(layout, "Column on Current Frame", 0, "GRAPH_OT_select_column", "mode", GRAPHKEYS_COLUMNSEL_CFRA);
|
||||
|
||||
uiItemEnumO(layout, "Columns on Selected Markers", 0, "GRAPH_OT_select_column", "mode", GRAPHKEYS_COLUMNSEL_MARKERS_COLUMN);
|
||||
uiItemEnumO(layout, "Between Selected Markers", 0, "GRAPH_OT_select_column", "mode", GRAPHKEYS_COLUMNSEL_MARKERS_BETWEEN);
|
||||
}
|
||||
|
||||
static void graph_channelmenu(bContext *C, uiLayout *layout, void *arg_unused)
|
||||
{
|
||||
uiItemO(layout, NULL, 0, "ANIM_OT_channels_setting_toggle");
|
||||
uiItemO(layout, NULL, 0, "ANIM_OT_channels_setting_enable");
|
||||
uiItemO(layout, NULL, 0, "ANIM_OT_channels_setting_disable");
|
||||
|
||||
uiItemS(layout);
|
||||
|
||||
uiItemO(layout, NULL, 0, "ANIM_OT_channels_editable_toggle");
|
||||
|
||||
uiItemS(layout);
|
||||
|
||||
uiItemO(layout, NULL, 0, "ANIM_OT_channels_expand");
|
||||
uiItemO(layout, NULL, 0, "ANIM_OT_channels_collapse");
|
||||
}
|
||||
|
||||
static void graph_edit_transformmenu(bContext *C, uiLayout *layout, void *arg_unused)
|
||||
{
|
||||
uiItemEnumO(layout, "Grab/Move", 0, "TFM_OT_transform", "mode", TFM_TIME_TRANSLATE);
|
||||
uiItemEnumO(layout, "Extend", 0, "TFM_OT_transform", "mode", TFM_TIME_EXTEND);
|
||||
uiItemEnumO(layout, "Scale", 0, "TFM_OT_transform", "mode", TFM_TIME_SCALE);
|
||||
}
|
||||
|
||||
static void graph_edit_snapmenu(bContext *C, uiLayout *layout, void *arg_unused)
|
||||
{
|
||||
uiItemEnumO(layout, NULL, 0, "GRAPH_OT_snap", "type", GRAPHKEYS_SNAP_CFRA);
|
||||
uiItemEnumO(layout, NULL, 0, "GRAPH_OT_snap", "type", GRAPHKEYS_SNAP_NEAREST_FRAME);
|
||||
uiItemEnumO(layout, NULL, 0, "GRAPH_OT_snap", "type", GRAPHKEYS_SNAP_NEAREST_SECOND);
|
||||
uiItemEnumO(layout, NULL, 0, "GRAPH_OT_snap", "type", GRAPHKEYS_SNAP_NEAREST_MARKER);
|
||||
}
|
||||
|
||||
static void graph_edit_mirrormenu(bContext *C, uiLayout *layout, void *arg_unused)
|
||||
{
|
||||
uiItemEnumO(layout, NULL, 0, "GRAPH_OT_mirror", "type", GRAPHKEYS_MIRROR_CFRA);
|
||||
uiItemEnumO(layout, NULL, 0, "GRAPH_OT_mirror", "type", GRAPHKEYS_MIRROR_YAXIS);
|
||||
uiItemEnumO(layout, NULL, 0, "GRAPH_OT_mirror", "type", GRAPHKEYS_MIRROR_XAXIS);
|
||||
uiItemEnumO(layout, NULL, 0, "GRAPH_OT_mirror", "type", GRAPHKEYS_MIRROR_MARKER);
|
||||
}
|
||||
|
||||
static void graph_edit_handlesmenu(bContext *C, uiLayout *layout, void *arg_unused)
|
||||
{
|
||||
uiItemEnumO(layout, NULL, 0, "GRAPH_OT_handle_type", "type", HD_FREE);
|
||||
uiItemEnumO(layout, NULL, 0, "GRAPH_OT_handle_type", "type", HD_AUTO);
|
||||
uiItemEnumO(layout, NULL, 0, "GRAPH_OT_handle_type", "type", HD_VECT);
|
||||
uiItemEnumO(layout, NULL, 0, "GRAPH_OT_handle_type", "type", HD_ALIGN);
|
||||
uiItemEnumO(layout, NULL, 0, "GRAPH_OT_handle_type", "type", HD_AUTO_ANIM); // xxx?
|
||||
}
|
||||
|
||||
static void graph_edit_ipomenu(bContext *C, uiLayout *layout, void *arg_unused)
|
||||
{
|
||||
uiItemEnumO(layout, NULL, 0, "GRAPH_OT_interpolation_type", "type", BEZT_IPO_CONST);
|
||||
uiItemEnumO(layout, NULL, 0, "GRAPH_OT_interpolation_type", "type", BEZT_IPO_LIN);
|
||||
uiItemEnumO(layout, NULL, 0, "GRAPH_OT_interpolation_type", "type", BEZT_IPO_BEZ);
|
||||
}
|
||||
|
||||
static void graph_edit_expomenu(bContext *C, uiLayout *layout, void *arg_unused)
|
||||
{
|
||||
uiItemEnumO(layout, NULL, 0, "GRAPH_OT_extrapolation_type", "type", FCURVE_EXTRAPOLATE_CONSTANT);
|
||||
uiItemEnumO(layout, NULL, 0, "GRAPH_OT_extrapolation_type", "type", FCURVE_EXTRAPOLATE_LINEAR);
|
||||
}
|
||||
|
||||
static void graph_editmenu(bContext *C, uiLayout *layout, void *arg_unused)
|
||||
{
|
||||
uiItemMenuF(layout, "Transform", 0, graph_edit_transformmenu);
|
||||
uiItemMenuF(layout, "Snap", 0, graph_edit_snapmenu);
|
||||
uiItemMenuF(layout, "Mirror", 0, graph_edit_mirrormenu);
|
||||
|
||||
uiItemS(layout);
|
||||
|
||||
uiItemO(layout, NULL, 0, "GRAPH_OT_insert_keyframe");
|
||||
uiItemO(layout, NULL, 0, "GRAPH_OT_fmodifier_add");
|
||||
|
||||
uiItemS(layout);
|
||||
|
||||
uiItemO(layout, NULL, 0, "GRAPH_OT_duplicate");
|
||||
uiItemO(layout, NULL, 0, "GRAPH_OT_delete");
|
||||
|
||||
uiItemS(layout);
|
||||
|
||||
uiItemMenuF(layout, "Handle Type", 0, graph_edit_handlesmenu);
|
||||
uiItemMenuF(layout, "Interpolation Mode", 0, graph_edit_ipomenu);
|
||||
uiItemMenuF(layout, "Extrapolation Mode", 0, graph_edit_expomenu);
|
||||
|
||||
uiItemS(layout);
|
||||
|
||||
uiItemO(layout, NULL, 0, "GRAPH_OT_clean");
|
||||
uiItemO(layout, NULL, 0, "GRAPH_OT_sample");
|
||||
|
||||
uiItemS(layout);
|
||||
|
||||
uiItemO(layout, NULL, 0, "GRAPH_OT_copy");
|
||||
uiItemO(layout, NULL, 0, "GRAPH_OT_paste");
|
||||
}
|
||||
|
||||
/* ********************************************************* */
|
||||
|
||||
enum {
|
||||
B_REDR = 0,
|
||||
B_REDR = 0,
|
||||
B_MODECHANGE,
|
||||
} eActHeader_ButEvents;
|
||||
|
||||
/* ************************ header area region *********************** */
|
||||
|
||||
static void do_viewmenu(bContext *C, void *arg, int event)
|
||||
{
|
||||
SpaceIpo *sipo= (SpaceIpo *)CTX_wm_space_data(C);
|
||||
|
||||
switch (event) {
|
||||
case 1: /* Show time/frames */
|
||||
sipo->flag ^= SIPO_DRAWTIME;
|
||||
break;
|
||||
case 2: /* AutoMerge Keyframes */
|
||||
sipo->flag ^= SIPO_NOTRANSKEYCULL;
|
||||
break;
|
||||
case 3: /* Show/Hide handles */
|
||||
sipo->flag ^= SIPO_NOHANDLES;
|
||||
break;
|
||||
case 4: /* Show current frame number beside indicator */
|
||||
sipo->flag ^= SIPO_NODRAWCFRANUM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uiBlock *graph_viewmenu(bContext *C, ARegion *ar, void *arg_unused)
|
||||
{
|
||||
ScrArea *curarea= CTX_wm_area(C);
|
||||
SpaceIpo *sipo= (SpaceIpo *)CTX_wm_space_data(C);
|
||||
uiBlock *block;
|
||||
short yco= 0, menuwidth=120;
|
||||
|
||||
block= uiBeginBlock(C, ar, "graph_viewmenu", UI_EMBOSSP);
|
||||
uiBlockSetButmFunc(block, do_viewmenu, NULL);
|
||||
|
||||
// XXX these options should use new menu-options
|
||||
|
||||
if (sipo->flag & SIPO_DRAWTIME) {
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Show Frames|Ctrl T", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
|
||||
}
|
||||
else {
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
|
||||
"Show Seconds|Ctrl T", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
|
||||
}
|
||||
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, (sipo->flag & SIPO_NOTRANSKEYCULL)?ICON_CHECKBOX_DEHLT:ICON_CHECKBOX_HLT,
|
||||
"AutoMerge Keyframes|", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, (sipo->flag & SIPO_NOHANDLES)?ICON_CHECKBOX_DEHLT:ICON_CHECKBOX_HLT,
|
||||
"Show Handles|Ctrl H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, (sipo->flag & SIPO_NODRAWCFRANUM)?ICON_CHECKBOX_DEHLT:ICON_CHECKBOX_HLT,
|
||||
"Show Current Frame Number|", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
|
||||
|
||||
if (curarea->headertype==HEADERTOP) {
|
||||
uiBlockSetDirection(block, UI_DOWN);
|
||||
}
|
||||
else {
|
||||
uiBlockSetDirection(block, UI_TOP);
|
||||
uiBlockFlipOrder(block);
|
||||
}
|
||||
|
||||
uiTextBoundsBlock(block, 50);
|
||||
uiEndBlock(C, block);
|
||||
|
||||
return block;
|
||||
}
|
||||
} eGraphEdit_Events;
|
||||
|
||||
static void do_graph_buttons(bContext *C, void *arg, int event)
|
||||
{
|
||||
@@ -163,8 +263,19 @@ void graph_header_buttons(const bContext *C, ARegion *ar)
|
||||
int xmax;
|
||||
|
||||
xmax= GetButStringLength("View");
|
||||
uiDefPulldownBut(block, graph_viewmenu, CTX_wm_area(C),
|
||||
"View", xco, yco-2, xmax-3, 24, "");
|
||||
uiDefMenuBut(block, graph_viewmenu, NULL, "View", xco, yco, xmax-3, 20, "");
|
||||
xco+= xmax;
|
||||
|
||||
xmax= GetButStringLength("Select");
|
||||
uiDefMenuBut(block, graph_selectmenu, NULL, "Select", xco, yco, xmax-3, 20, "");
|
||||
xco+= xmax;
|
||||
|
||||
xmax= GetButStringLength("Channel");
|
||||
uiDefMenuBut(block, graph_channelmenu, NULL, "Channel", xco, yco, xmax-3, 20, "");
|
||||
xco+= xmax;
|
||||
|
||||
xmax= GetButStringLength("Key");
|
||||
uiDefMenuBut(block, graph_editmenu, NULL, "Key", xco, yco, xmax-3, 20, "");
|
||||
xco+= xmax;
|
||||
}
|
||||
|
||||
@@ -202,8 +313,8 @@ void graph_header_buttons(const bContext *C, ARegion *ar)
|
||||
|
||||
/* copy + paste */
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefIconButO(block, BUT, "GRAPHEDIT_OT_keyframes_copy", WM_OP_INVOKE_REGION_WIN, ICON_COPYDOWN, xco+=XIC,yco,XIC,YIC, "Copies the selected keyframes from the selected channel(s) to the buffer");
|
||||
uiDefIconButO(block, BUT, "GRAPHEDIT_OT_keyframes_paste", WM_OP_INVOKE_REGION_WIN, ICON_PASTEDOWN, xco+=XIC,yco,XIC,YIC, "Pastes the keyframes from the buffer");
|
||||
uiDefIconButO(block, BUT, "GRAPH_OT_copy", WM_OP_INVOKE_REGION_WIN, ICON_COPYDOWN, xco+=XIC,yco,XIC,YIC, "Copies the selected keyframes from the selected channel(s) to the buffer");
|
||||
uiDefIconButO(block, BUT, "GRAPH_OT_paste", WM_OP_INVOKE_REGION_WIN, ICON_PASTEDOWN, xco+=XIC,yco,XIC,YIC, "Pastes the keyframes from the buffer");
|
||||
uiBlockEndAlign(block);
|
||||
xco += (XIC + 8);
|
||||
|
||||
@@ -225,9 +336,9 @@ void graph_header_buttons(const bContext *C, ARegion *ar)
|
||||
/* ghost curves */
|
||||
// XXX these icons need to be changed
|
||||
if (sipo->ghostCurves.first)
|
||||
uiDefIconButO(block, BUT, "GRAPHEDIT_OT_ghost_curves_clear", WM_OP_INVOKE_REGION_WIN, ICON_OUTLINER_DATA_CURVE, xco,yco,XIC,YIC, "Clear F-Curve snapshots (Ghosts) for this Graph Editor instance");
|
||||
uiDefIconButO(block, BUT, "GRAPH_OT_ghost_curves_clear", WM_OP_INVOKE_REGION_WIN, ICON_OUTLINER_DATA_CURVE, xco,yco,XIC,YIC, "Clear F-Curve snapshots (Ghosts) for this Graph Editor instance");
|
||||
else
|
||||
uiDefIconButO(block, BUT, "GRAPHEDIT_OT_ghost_curves_create", WM_OP_INVOKE_REGION_WIN, ICON_OUTLINER_OB_CURVE, xco,yco,XIC,YIC, "Create snapshot (Ghosts) of selected F-Curves as background aid for this Graph Editor instance");
|
||||
uiDefIconButO(block, BUT, "GRAPH_OT_ghost_curves_create", WM_OP_INVOKE_REGION_WIN, ICON_OUTLINER_OB_CURVE, xco,yco,XIC,YIC, "Create snapshot (Ghosts) of selected F-Curves as background aid for this Graph Editor instance");
|
||||
xco+= XIC;
|
||||
|
||||
|
||||
|
||||
@@ -32,6 +32,8 @@ struct bContext;
|
||||
struct wmWindowManager;
|
||||
struct bAnimContext;
|
||||
struct bAnimListElem;
|
||||
struct FCurve;
|
||||
struct FModifier;
|
||||
struct SpaceIpo;
|
||||
struct ScrArea;
|
||||
struct ARegion;
|
||||
@@ -58,10 +60,10 @@ void graph_header_buttons(const bContext *C, struct ARegion *ar);
|
||||
/* ***************************************** */
|
||||
/* graph_select.c */
|
||||
|
||||
void GRAPHEDIT_OT_keyframes_select_all_toggle(struct wmOperatorType *ot);
|
||||
void GRAPHEDIT_OT_keyframes_select_border(struct wmOperatorType *ot);
|
||||
void GRAPHEDIT_OT_keyframes_columnselect(struct wmOperatorType *ot);
|
||||
void GRAPHEDIT_OT_keyframes_clickselect(struct wmOperatorType *ot);
|
||||
void GRAPH_OT_select_all_toggle(struct wmOperatorType *ot);
|
||||
void GRAPH_OT_select_border(struct wmOperatorType *ot);
|
||||
void GRAPH_OT_select_column(struct wmOperatorType *ot);
|
||||
void GRAPH_OT_clickselect(struct wmOperatorType *ot);
|
||||
|
||||
/* defines for left-right select tool */
|
||||
enum {
|
||||
@@ -84,28 +86,29 @@ enum {
|
||||
|
||||
void get_graph_keyframe_extents (struct bAnimContext *ac, float *xmin, float *xmax, float *ymin, float *ymax);
|
||||
|
||||
void GRAPHEDIT_OT_previewrange_set(struct wmOperatorType *ot);
|
||||
void GRAPHEDIT_OT_view_all(struct wmOperatorType *ot);
|
||||
void GRAPH_OT_previewrange_set(struct wmOperatorType *ot);
|
||||
void GRAPH_OT_view_all(struct wmOperatorType *ot);
|
||||
|
||||
void GRAPHEDIT_OT_keyframes_click_insert(struct wmOperatorType *ot);
|
||||
void GRAPH_OT_click_insert(struct wmOperatorType *ot);
|
||||
void GRAPH_OT_insert_keyframe(struct wmOperatorType *ot);
|
||||
|
||||
void GRAPHEDIT_OT_keyframes_copy(struct wmOperatorType *ot);
|
||||
void GRAPHEDIT_OT_keyframes_paste(struct wmOperatorType *ot);
|
||||
void GRAPH_OT_copy(struct wmOperatorType *ot);
|
||||
void GRAPH_OT_paste(struct wmOperatorType *ot);
|
||||
|
||||
void GRAPHEDIT_OT_keyframes_duplicate(struct wmOperatorType *ot);
|
||||
void GRAPHEDIT_OT_keyframes_delete(struct wmOperatorType *ot);
|
||||
void GRAPHEDIT_OT_keyframes_clean(struct wmOperatorType *ot);
|
||||
void GRAPHEDIT_OT_keyframes_sample(struct wmOperatorType *ot);
|
||||
void GRAPHEDIT_OT_keyframes_bake(struct wmOperatorType *ot);
|
||||
void GRAPHEDIT_OT_keyframes_smooth(struct wmOperatorType *ot);
|
||||
void GRAPH_OT_duplicate(struct wmOperatorType *ot);
|
||||
void GRAPH_OT_delete(struct wmOperatorType *ot);
|
||||
void GRAPH_OT_clean(struct wmOperatorType *ot);
|
||||
void GRAPH_OT_sample(struct wmOperatorType *ot);
|
||||
void GRAPH_OT_bake(struct wmOperatorType *ot);
|
||||
void GRAPH_OT_smooth(struct wmOperatorType *ot);
|
||||
|
||||
void GRAPHEDIT_OT_keyframes_handletype(struct wmOperatorType *ot);
|
||||
void GRAPHEDIT_OT_keyframes_interpolation_type(struct wmOperatorType *ot);
|
||||
void GRAPHEDIT_OT_keyframes_extrapolation_type(struct wmOperatorType *ot);
|
||||
void GRAPH_OT_handletype(struct wmOperatorType *ot);
|
||||
void GRAPH_OT_interpolation_type(struct wmOperatorType *ot);
|
||||
void GRAPH_OT_extrapolation_type(struct wmOperatorType *ot);
|
||||
|
||||
void GRAPHEDIT_OT_keyframes_cfrasnap(struct wmOperatorType *ot);
|
||||
void GRAPHEDIT_OT_keyframes_snap(struct wmOperatorType *ot);
|
||||
void GRAPHEDIT_OT_keyframes_mirror(struct wmOperatorType *ot);
|
||||
void GRAPH_OT_frame_jump(struct wmOperatorType *ot);
|
||||
void GRAPH_OT_snap(struct wmOperatorType *ot);
|
||||
void GRAPH_OT_mirror(struct wmOperatorType *ot);
|
||||
|
||||
/* defines for snap keyframes
|
||||
* NOTE: keep in sync with eEditKeyframes_Snap (in ED_keyframes_edit.h)
|
||||
@@ -130,20 +133,29 @@ enum {
|
||||
|
||||
/* ----------- */
|
||||
|
||||
void GRAPHEDIT_OT_fmodifier_add(struct wmOperatorType *ot);
|
||||
void GRAPH_OT_fmodifier_add(struct wmOperatorType *ot);
|
||||
|
||||
/* ----------- */
|
||||
|
||||
void GRAPHEDIT_OT_ghost_curves_create(struct wmOperatorType *ot);
|
||||
void GRAPHEDIT_OT_ghost_curves_clear(struct wmOperatorType *ot);
|
||||
void GRAPH_OT_ghost_curves_create(struct wmOperatorType *ot);
|
||||
void GRAPH_OT_ghost_curves_clear(struct wmOperatorType *ot);
|
||||
|
||||
/* ***************************************** */
|
||||
/* graph_buttons.c */
|
||||
void GRAPHEDIT_OT_properties(struct wmOperatorType *ot);
|
||||
void GRAPH_OT_properties(struct wmOperatorType *ot);
|
||||
void graph_buttons_register(struct ARegionType *art);
|
||||
|
||||
/* ***************************************** */
|
||||
/* graph_utils.c */
|
||||
|
||||
struct bAnimListElem *get_active_fcurve_channel(struct bAnimContext *ac);
|
||||
|
||||
short fcurve_needs_draw_fmodifier_controls(struct FCurve *fcu, struct FModifier *fcm);
|
||||
|
||||
int graphop_visible_keyframes_poll(struct bContext *C);
|
||||
int graphop_editable_keyframes_poll(struct bContext *C);
|
||||
int graphop_active_fcurve_poll(struct bContext *C);
|
||||
|
||||
/* ***************************************** */
|
||||
/* graph_ops.c */
|
||||
void graphedit_keymap(struct wmWindowManager *wm);
|
||||
|
||||
@@ -57,6 +57,10 @@
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
|
||||
/* ************************** poll callbacks **********************************/
|
||||
|
||||
|
||||
|
||||
/* ************************** view-based operators **********************************/
|
||||
// XXX this probably shouldn't be here..
|
||||
|
||||
@@ -79,15 +83,15 @@ static int view_toggle_handles_exec (bContext *C, wmOperator *op)
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void GRAPHEDIT_OT_view_togglehandles (wmOperatorType *ot)
|
||||
void GRAPH_OT_view_togglehandles (wmOperatorType *ot)
|
||||
{
|
||||
/* identification */
|
||||
ot->name= "Show/Hide All Handles";
|
||||
ot->idname= "GRAPHEDIT_OT_handles_view_toggle";
|
||||
ot->idname= "GRAPH_OT_handles_view_toggle";
|
||||
|
||||
/* callbacks */
|
||||
ot->exec= view_toggle_handles_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= ED_operator_ipo_active;
|
||||
}
|
||||
|
||||
/* ************************** registration - operator types **********************************/
|
||||
@@ -95,45 +99,44 @@ void GRAPHEDIT_OT_view_togglehandles (wmOperatorType *ot)
|
||||
void graphedit_operatortypes(void)
|
||||
{
|
||||
/* view */
|
||||
WM_operatortype_append(GRAPHEDIT_OT_view_togglehandles);
|
||||
WM_operatortype_append(GRAPHEDIT_OT_previewrange_set);
|
||||
WM_operatortype_append(GRAPHEDIT_OT_view_all);
|
||||
WM_operatortype_append(GRAPHEDIT_OT_properties);
|
||||
WM_operatortype_append(GRAPH_OT_view_togglehandles);
|
||||
WM_operatortype_append(GRAPH_OT_previewrange_set);
|
||||
WM_operatortype_append(GRAPH_OT_view_all);
|
||||
WM_operatortype_append(GRAPH_OT_properties);
|
||||
|
||||
WM_operatortype_append(GRAPHEDIT_OT_ghost_curves_create);
|
||||
WM_operatortype_append(GRAPHEDIT_OT_ghost_curves_clear);
|
||||
WM_operatortype_append(GRAPH_OT_ghost_curves_create);
|
||||
WM_operatortype_append(GRAPH_OT_ghost_curves_clear);
|
||||
|
||||
/* keyframes */
|
||||
/* selection */
|
||||
WM_operatortype_append(GRAPHEDIT_OT_keyframes_clickselect);
|
||||
WM_operatortype_append(GRAPHEDIT_OT_keyframes_select_all_toggle);
|
||||
WM_operatortype_append(GRAPHEDIT_OT_keyframes_select_border);
|
||||
WM_operatortype_append(GRAPHEDIT_OT_keyframes_columnselect);
|
||||
WM_operatortype_append(GRAPH_OT_clickselect);
|
||||
WM_operatortype_append(GRAPH_OT_select_all_toggle);
|
||||
WM_operatortype_append(GRAPH_OT_select_border);
|
||||
WM_operatortype_append(GRAPH_OT_select_column);
|
||||
|
||||
/* editing */
|
||||
WM_operatortype_append(GRAPHEDIT_OT_keyframes_snap);
|
||||
WM_operatortype_append(GRAPHEDIT_OT_keyframes_mirror);
|
||||
WM_operatortype_append(GRAPHEDIT_OT_keyframes_cfrasnap);
|
||||
WM_operatortype_append(GRAPHEDIT_OT_keyframes_handletype);
|
||||
WM_operatortype_append(GRAPHEDIT_OT_keyframes_interpolation_type);
|
||||
WM_operatortype_append(GRAPHEDIT_OT_keyframes_extrapolation_type);
|
||||
WM_operatortype_append(GRAPHEDIT_OT_keyframes_sample);
|
||||
WM_operatortype_append(GRAPHEDIT_OT_keyframes_bake);
|
||||
WM_operatortype_append(GRAPHEDIT_OT_keyframes_smooth);
|
||||
WM_operatortype_append(GRAPHEDIT_OT_keyframes_clean);
|
||||
WM_operatortype_append(GRAPHEDIT_OT_keyframes_delete);
|
||||
WM_operatortype_append(GRAPHEDIT_OT_keyframes_duplicate);
|
||||
WM_operatortype_append(GRAPH_OT_snap);
|
||||
WM_operatortype_append(GRAPH_OT_mirror);
|
||||
WM_operatortype_append(GRAPH_OT_frame_jump);
|
||||
WM_operatortype_append(GRAPH_OT_handletype);
|
||||
WM_operatortype_append(GRAPH_OT_interpolation_type);
|
||||
WM_operatortype_append(GRAPH_OT_extrapolation_type);
|
||||
WM_operatortype_append(GRAPH_OT_sample);
|
||||
WM_operatortype_append(GRAPH_OT_bake);
|
||||
WM_operatortype_append(GRAPH_OT_smooth);
|
||||
WM_operatortype_append(GRAPH_OT_clean);
|
||||
WM_operatortype_append(GRAPH_OT_delete);
|
||||
WM_operatortype_append(GRAPH_OT_duplicate);
|
||||
|
||||
WM_operatortype_append(GRAPHEDIT_OT_keyframes_copy);
|
||||
WM_operatortype_append(GRAPHEDIT_OT_keyframes_paste);
|
||||
WM_operatortype_append(GRAPH_OT_copy);
|
||||
WM_operatortype_append(GRAPH_OT_paste);
|
||||
|
||||
WM_operatortype_append(GRAPHEDIT_OT_keyframes_click_insert);
|
||||
|
||||
//TODO: insertkey...
|
||||
WM_operatortype_append(GRAPH_OT_insert_keyframe);
|
||||
WM_operatortype_append(GRAPH_OT_click_insert);
|
||||
|
||||
/* F-Curve Modifiers */
|
||||
// XXX temporary?
|
||||
WM_operatortype_append(GRAPHEDIT_OT_fmodifier_add);
|
||||
WM_operatortype_append(GRAPH_OT_fmodifier_add);
|
||||
}
|
||||
|
||||
/* ************************** registration - keymaps **********************************/
|
||||
@@ -143,81 +146,82 @@ static void graphedit_keymap_keyframes (wmWindowManager *wm, ListBase *keymap)
|
||||
wmKeymapItem *kmi;
|
||||
|
||||
/* view */
|
||||
WM_keymap_add_item(keymap, "GRAPHEDIT_OT_handles_view_toggle", HKEY, KM_PRESS, KM_CTRL, 0);
|
||||
WM_keymap_add_item(keymap, "GRAPH_OT_handles_view_toggle", HKEY, KM_PRESS, KM_CTRL, 0);
|
||||
|
||||
/* graph_select.c - selection tools */
|
||||
/* click-select */
|
||||
WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_clickselect", SELECTMOUSE, KM_PRESS, 0, 0);
|
||||
kmi= WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_clickselect", SELECTMOUSE, KM_PRESS, KM_ALT, 0);
|
||||
WM_keymap_add_item(keymap, "GRAPH_OT_clickselect", SELECTMOUSE, KM_PRESS, 0, 0);
|
||||
kmi= WM_keymap_add_item(keymap, "GRAPH_OT_clickselect", SELECTMOUSE, KM_PRESS, KM_ALT, 0);
|
||||
RNA_boolean_set(kmi->ptr, "column", 1);
|
||||
kmi= WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_clickselect", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0);
|
||||
kmi= WM_keymap_add_item(keymap, "GRAPH_OT_clickselect", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0);
|
||||
RNA_boolean_set(kmi->ptr, "extend", 1);
|
||||
kmi= WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_clickselect", SELECTMOUSE, KM_PRESS, KM_ALT|KM_SHIFT, 0);
|
||||
kmi= WM_keymap_add_item(keymap, "GRAPH_OT_clickselect", SELECTMOUSE, KM_PRESS, KM_ALT|KM_SHIFT, 0);
|
||||
RNA_boolean_set(kmi->ptr, "extend", 1);
|
||||
RNA_boolean_set(kmi->ptr, "column", 1);
|
||||
kmi= WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_clickselect", SELECTMOUSE, KM_PRESS, KM_CTRL, 0);
|
||||
kmi= WM_keymap_add_item(keymap, "GRAPH_OT_clickselect", SELECTMOUSE, KM_PRESS, KM_CTRL, 0);
|
||||
RNA_enum_set(kmi->ptr, "left_right", GRAPHKEYS_LRSEL_TEST);
|
||||
kmi= WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_clickselect", SELECTMOUSE, KM_PRESS, KM_CTRL|KM_ALT, 0);
|
||||
kmi= WM_keymap_add_item(keymap, "GRAPH_OT_clickselect", SELECTMOUSE, KM_PRESS, KM_CTRL|KM_ALT, 0);
|
||||
RNA_boolean_set(kmi->ptr, "curves", 1);
|
||||
kmi= WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_clickselect", SELECTMOUSE, KM_PRESS, KM_CTRL|KM_ALT|KM_SHIFT, 0);
|
||||
kmi= WM_keymap_add_item(keymap, "GRAPH_OT_clickselect", SELECTMOUSE, KM_PRESS, KM_CTRL|KM_ALT|KM_SHIFT, 0);
|
||||
RNA_boolean_set(kmi->ptr, "curves", 1);
|
||||
RNA_boolean_set(kmi->ptr, "extend", 1);
|
||||
|
||||
/* deselect all */
|
||||
WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_select_all_toggle", AKEY, KM_PRESS, 0, 0);
|
||||
RNA_boolean_set(WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_select_all_toggle", IKEY, KM_PRESS, KM_CTRL, 0)->ptr, "invert", 1);
|
||||
WM_keymap_add_item(keymap, "GRAPH_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0);
|
||||
RNA_boolean_set(WM_keymap_add_item(keymap, "GRAPH_OT_select_all_toggle", IKEY, KM_PRESS, KM_CTRL, 0)->ptr, "invert", 1);
|
||||
|
||||
/* borderselect */
|
||||
WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_select_border", BKEY, KM_PRESS, 0, 0);
|
||||
RNA_boolean_set(WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_select_border", BKEY, KM_PRESS, KM_ALT, 0)->ptr, "axis_range", 1);
|
||||
WM_keymap_add_item(keymap, "GRAPH_OT_select_border", BKEY, KM_PRESS, 0, 0);
|
||||
RNA_boolean_set(WM_keymap_add_item(keymap, "GRAPH_OT_select_border", BKEY, KM_PRESS, KM_ALT, 0)->ptr, "axis_range", 1);
|
||||
|
||||
/* column select */
|
||||
// XXX KKEY would be nice to keep for 'keyframe' lines
|
||||
RNA_enum_set(WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_columnselect", KKEY, KM_PRESS, 0, 0)->ptr, "mode", GRAPHKEYS_COLUMNSEL_KEYS);
|
||||
RNA_enum_set(WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_columnselect", KKEY, KM_PRESS, KM_CTRL, 0)->ptr, "mode", GRAPHKEYS_COLUMNSEL_CFRA);
|
||||
RNA_enum_set(WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_columnselect", KKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "mode", GRAPHKEYS_COLUMNSEL_MARKERS_COLUMN);
|
||||
RNA_enum_set(WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_columnselect", KKEY, KM_PRESS, KM_ALT, 0)->ptr, "mode", GRAPHKEYS_COLUMNSEL_MARKERS_BETWEEN);
|
||||
RNA_enum_set(WM_keymap_add_item(keymap, "GRAPH_OT_select_column", KKEY, KM_PRESS, 0, 0)->ptr, "mode", GRAPHKEYS_COLUMNSEL_KEYS);
|
||||
RNA_enum_set(WM_keymap_add_item(keymap, "GRAPH_OT_select_column", KKEY, KM_PRESS, KM_CTRL, 0)->ptr, "mode", GRAPHKEYS_COLUMNSEL_CFRA);
|
||||
RNA_enum_set(WM_keymap_add_item(keymap, "GRAPH_OT_select_column", KKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "mode", GRAPHKEYS_COLUMNSEL_MARKERS_COLUMN);
|
||||
RNA_enum_set(WM_keymap_add_item(keymap, "GRAPH_OT_select_column", KKEY, KM_PRESS, KM_ALT, 0)->ptr, "mode", GRAPHKEYS_COLUMNSEL_MARKERS_BETWEEN);
|
||||
|
||||
|
||||
/* graph_edit.c */
|
||||
/* snap - current frame to selected keys */
|
||||
WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_cfrasnap", SKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0);
|
||||
// TODO: maybe since this is called jump, we're better to have it on <something>-J?
|
||||
WM_keymap_add_item(keymap, "GRAPH_OT_frame_jump", SKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0);
|
||||
|
||||
/* menu + single-step transform */
|
||||
WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_snap", SKEY, KM_PRESS, KM_SHIFT, 0);
|
||||
WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_mirror", MKEY, KM_PRESS, KM_SHIFT, 0);
|
||||
WM_keymap_add_item(keymap, "GRAPH_OT_snap", SKEY, KM_PRESS, KM_SHIFT, 0);
|
||||
WM_keymap_add_item(keymap, "GRAPH_OT_mirror", MKEY, KM_PRESS, KM_SHIFT, 0);
|
||||
|
||||
WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_handletype", HKEY, KM_PRESS, 0, 0);
|
||||
WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_interpolation_type", TKEY, KM_PRESS, KM_SHIFT, 0);
|
||||
WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_extrapolation_type", EKEY, KM_PRESS, KM_SHIFT, 0);
|
||||
WM_keymap_add_item(keymap, "GRAPH_OT_handletype", HKEY, KM_PRESS, 0, 0);
|
||||
WM_keymap_add_item(keymap, "GRAPH_OT_interpolation_type", TKEY, KM_PRESS, KM_SHIFT, 0);
|
||||
WM_keymap_add_item(keymap, "GRAPH_OT_extrapolation_type", EKEY, KM_PRESS, KM_SHIFT, 0);
|
||||
|
||||
|
||||
/* destructive */
|
||||
WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_clean", OKEY, KM_PRESS, 0, 0);
|
||||
WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_smooth", OKEY, KM_PRESS, KM_ALT, 0);
|
||||
WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_sample", OKEY, KM_PRESS, KM_SHIFT, 0);
|
||||
WM_keymap_add_item(keymap, "GRAPH_OT_clean", OKEY, KM_PRESS, 0, 0);
|
||||
WM_keymap_add_item(keymap, "GRAPH_OT_smooth", OKEY, KM_PRESS, KM_ALT, 0);
|
||||
WM_keymap_add_item(keymap, "GRAPH_OT_sample", OKEY, KM_PRESS, KM_SHIFT, 0);
|
||||
|
||||
WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_bake", CKEY, KM_PRESS, KM_ALT, 0);
|
||||
WM_keymap_add_item(keymap, "GRAPH_OT_bake", CKEY, KM_PRESS, KM_ALT, 0);
|
||||
|
||||
WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_delete", XKEY, KM_PRESS, 0, 0);
|
||||
WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_delete", DELKEY, KM_PRESS, 0, 0);
|
||||
WM_keymap_add_item(keymap, "GRAPH_OT_delete", XKEY, KM_PRESS, 0, 0);
|
||||
WM_keymap_add_item(keymap, "GRAPH_OT_delete", DELKEY, KM_PRESS, 0, 0);
|
||||
|
||||
WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_duplicate", DKEY, KM_PRESS, KM_SHIFT, 0);
|
||||
WM_keymap_add_item(keymap, "GRAPH_OT_duplicate", DKEY, KM_PRESS, KM_SHIFT, 0);
|
||||
|
||||
/* insertkey */
|
||||
WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_click_insert", LEFTMOUSE, KM_PRESS, KM_CTRL, 0);
|
||||
WM_keymap_add_item(keymap, "GRAPH_OT_insert_keyframe", IKEY, KM_PRESS, 0, 0);
|
||||
WM_keymap_add_item(keymap, "GRAPH_OT_click_insert", LEFTMOUSE, KM_PRESS, KM_CTRL, 0);
|
||||
|
||||
/* copy/paste */
|
||||
WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_copy", CKEY, KM_PRESS, KM_CTRL, 0);
|
||||
WM_keymap_add_item(keymap, "GRAPHEDIT_OT_keyframes_paste", VKEY, KM_PRESS, KM_CTRL, 0);
|
||||
WM_keymap_add_item(keymap, "GRAPH_OT_copy", CKEY, KM_PRESS, KM_CTRL, 0);
|
||||
WM_keymap_add_item(keymap, "GRAPH_OT_paste", VKEY, KM_PRESS, KM_CTRL, 0);
|
||||
|
||||
/* auto-set range */
|
||||
WM_keymap_add_item(keymap, "GRAPHEDIT_OT_previewrange_set", PKEY, KM_PRESS, KM_CTRL|KM_ALT, 0);
|
||||
WM_keymap_add_item(keymap, "GRAPHEDIT_OT_view_all", HOMEKEY, KM_PRESS, 0, 0);
|
||||
WM_keymap_add_item(keymap, "GRAPH_OT_previewrange_set", PKEY, KM_PRESS, KM_CTRL|KM_ALT, 0);
|
||||
WM_keymap_add_item(keymap, "GRAPH_OT_view_all", HOMEKEY, KM_PRESS, 0, 0);
|
||||
|
||||
/* F-Curve Modifiers */
|
||||
// XXX these are temporary? operators...
|
||||
WM_keymap_add_item(keymap, "GRAPHEDIT_OT_fmodifier_add", MKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0);
|
||||
/* F-Modifiers */
|
||||
WM_keymap_add_item(keymap, "GRAPH_OT_fmodifier_add", MKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0);
|
||||
|
||||
|
||||
/* transform system */
|
||||
@@ -232,7 +236,7 @@ void graphedit_keymap(wmWindowManager *wm)
|
||||
|
||||
/* keymap for all regions */
|
||||
keymap= WM_keymap_listbase(wm, "GraphEdit Generic", SPACE_IPO, 0);
|
||||
WM_keymap_add_item(keymap, "GRAPHEDIT_OT_properties", NKEY, KM_PRESS, 0, 0);
|
||||
WM_keymap_add_item(keymap, "GRAPH_OT_properties", NKEY, KM_PRESS, 0, 0);
|
||||
|
||||
/* channels */
|
||||
/* Channels are not directly handled by the Graph Editor module, but are inherited from the Animation module.
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
#include "BKE_fcurve.h"
|
||||
#include "BKE_key.h"
|
||||
#include "BKE_material.h"
|
||||
#include "BKE_nla.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_utildefines.h"
|
||||
@@ -168,20 +169,20 @@ static int graphkeys_deselectall_exec(bContext *C, wmOperator *op)
|
||||
deselect_graph_keys(&ac, 1, SELECT_ADD);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
ED_area_tag_redraw(CTX_wm_area(C)); // FIXME... should be updating 'keyframes' data context or so instead!
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_SELECT, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void GRAPHEDIT_OT_keyframes_select_all_toggle (wmOperatorType *ot)
|
||||
void GRAPH_OT_select_all_toggle (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Select All";
|
||||
ot->idname= "GRAPHEDIT_OT_keyframes_select_all_toggle";
|
||||
ot->idname= "GRAPH_OT_select_all_toggle";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= graphkeys_deselectall_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= graphop_visible_keyframes_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
|
||||
@@ -231,14 +232,14 @@ static void borderselect_graphkeys (bAnimContext *ac, rcti rect, short mode, sho
|
||||
|
||||
/* loop over data, doing border select */
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
Object *nob= ANIM_nla_mapping_get(ac, ale);
|
||||
AnimData *adt= ANIM_nla_mapping_get(ac, ale);
|
||||
|
||||
/* set horizontal range (if applicable) */
|
||||
if (mode != BEZT_OK_VALUERANGE) {
|
||||
/* if channel is mapped in NLA, apply correction */
|
||||
if (nob) {
|
||||
bed.f1= get_action_frame(nob, rectf.xmin);
|
||||
bed.f2= get_action_frame(nob, rectf.xmax);
|
||||
if (adt) {
|
||||
bed.f1= BKE_nla_tweakedit_remap(adt, rectf.xmin, NLATIME_CONVERT_UNMAP);
|
||||
bed.f2= BKE_nla_tweakedit_remap(adt, rectf.xmax, NLATIME_CONVERT_UNMAP);
|
||||
}
|
||||
else {
|
||||
bed.f1= rectf.xmin;
|
||||
@@ -301,21 +302,24 @@ static int graphkeys_borderselect_exec(bContext *C, wmOperator *op)
|
||||
/* apply borderselect action */
|
||||
borderselect_graphkeys(&ac, rect, mode, selectmode);
|
||||
|
||||
/* send notifier that keyframe selection has changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_SELECT, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void GRAPHEDIT_OT_keyframes_select_border(wmOperatorType *ot)
|
||||
void GRAPH_OT_select_border(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Border Select";
|
||||
ot->idname= "GRAPHEDIT_OT_keyframes_select_border";
|
||||
ot->idname= "GRAPH_OT_select_border";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke= WM_border_select_invoke;
|
||||
ot->exec= graphkeys_borderselect_exec;
|
||||
ot->modal= WM_border_select_modal;
|
||||
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= graphop_visible_keyframes_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
|
||||
@@ -379,12 +383,12 @@ static void markers_selectkeys_between (bAnimContext *ac)
|
||||
|
||||
/* select keys in-between */
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
Object *nob= ANIM_nla_mapping_get(ac, ale);
|
||||
AnimData *adt= ANIM_nla_mapping_get(ac, ale);
|
||||
|
||||
if (nob) {
|
||||
ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 0, 1);
|
||||
if (adt) {
|
||||
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
|
||||
ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL);
|
||||
ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 1, 1);
|
||||
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
|
||||
}
|
||||
else {
|
||||
ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL);
|
||||
@@ -450,15 +454,15 @@ static void columnselect_graph_keys (bAnimContext *ac, short mode)
|
||||
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
|
||||
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
Object *nob= ANIM_nla_mapping_get(ac, ale);
|
||||
AnimData *adt= ANIM_nla_mapping_get(ac, ale);
|
||||
|
||||
/* loop over cfraelems (stored in the BeztEditData->list)
|
||||
* - we need to do this here, as we can apply fewer NLA-mapping conversions
|
||||
*/
|
||||
for (ce= bed.list.first; ce; ce= ce->next) {
|
||||
/* set frame for validation callback to refer to */
|
||||
if (nob)
|
||||
bed.f1= get_action_frame(nob, ce->cfra);
|
||||
if (ale)
|
||||
bed.f1= BKE_nla_tweakedit_remap(adt, ce->cfra, NLATIME_CONVERT_UNMAP);
|
||||
else
|
||||
bed.f1= ce->cfra;
|
||||
|
||||
@@ -491,21 +495,21 @@ static int graphkeys_columnselect_exec(bContext *C, wmOperator *op)
|
||||
else
|
||||
columnselect_graph_keys(&ac, mode);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_SELECT);
|
||||
/* set notifier that keyframe selection has changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_SELECT, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void GRAPHEDIT_OT_keyframes_columnselect (wmOperatorType *ot)
|
||||
void GRAPH_OT_select_column (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Select All";
|
||||
ot->idname= "GRAPHEDIT_OT_keyframes_columnselect";
|
||||
ot->idname= "GRAPH_OT_select_column";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= graphkeys_columnselect_exec;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= graphop_visible_keyframes_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
|
||||
@@ -566,11 +570,16 @@ static short findnearest_fcurve_vert (bAnimContext *ac, int mval[2], FCurve **fc
|
||||
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
FCurve *fcu= (FCurve *)ale->key_data;
|
||||
AnimData *adt= ANIM_nla_mapping_get(ac, ale);
|
||||
|
||||
/* try to progressively get closer to the right point... */
|
||||
if (fcu->bezt) {
|
||||
BezTriple *bezt1=fcu->bezt, *prevbezt=NULL;
|
||||
|
||||
/* apply NLA mapping to all the keyframes */
|
||||
if (adt)
|
||||
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
|
||||
|
||||
for (i=0; i < fcu->totvert; i++, prevbezt=bezt1, bezt1++) {
|
||||
/* convert beztriple points to screen-space */
|
||||
UI_view2d_to_region_no_clip(v2d, bezt1->vec[0][0], bezt1->vec[0][1], &sco[0][0], &sco[0][1]);
|
||||
@@ -624,6 +633,10 @@ static short findnearest_fcurve_vert (bAnimContext *ac, int mval[2], FCurve **fc
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* un-apply NLA mapping from all the keyframes */
|
||||
if (adt)
|
||||
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -722,7 +735,7 @@ static void mouse_graph_keys (bAnimContext *ac, int mval[], short select_mode, s
|
||||
/* set active F-Curve (NOTE: sync the filter flags with findnearest_fcurve_vert) */
|
||||
if (fcu->flag & FCURVE_SELECTED) {
|
||||
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_CURVESONLY);
|
||||
ANIM_set_active_channel(ac->data, ac->datatype, filter, fcu, ANIMTYPE_FCURVE);
|
||||
ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ANIMTYPE_FCURVE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -753,7 +766,7 @@ static void graphkeys_mselect_leftright (bAnimContext *ac, short leftright, shor
|
||||
|
||||
memset(&bed, 0, sizeof(BeztEditFunc));
|
||||
if (leftright == GRAPHKEYS_LRSEL_LEFT) {
|
||||
bed.f1 = -MAXFRAMEF;
|
||||
bed.f1 = MINAFRAMEF;
|
||||
bed.f2 = (float)(CFRA + 0.1f);
|
||||
}
|
||||
else {
|
||||
@@ -767,12 +780,12 @@ static void graphkeys_mselect_leftright (bAnimContext *ac, short leftright, shor
|
||||
|
||||
/* select keys on the side where most data occurs */
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
Object *nob= ANIM_nla_mapping_get(ac, ale);
|
||||
AnimData *adt= ANIM_nla_mapping_get(ac, ale);
|
||||
|
||||
if (nob) {
|
||||
ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 0, 1);
|
||||
if (adt) {
|
||||
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
|
||||
ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL);
|
||||
ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 1, 1);
|
||||
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
|
||||
}
|
||||
else
|
||||
ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL);
|
||||
@@ -827,11 +840,11 @@ static void graphkeys_mselect_column (bAnimContext *ac, int mval[2], short selec
|
||||
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
|
||||
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
Object *nob= ANIM_nla_mapping_get(ac, ale);
|
||||
AnimData *adt= ANIM_nla_mapping_get(ac, ale);
|
||||
|
||||
/* set frame for validation callback to refer to */
|
||||
if (nob)
|
||||
bed.f1= get_action_frame(nob, selx);
|
||||
if (adt)
|
||||
bed.f1= BKE_nla_tweakedit_remap(adt, selx, NLATIME_CONVERT_UNMAP);
|
||||
else
|
||||
bed.f1= selx;
|
||||
|
||||
@@ -901,22 +914,22 @@ static int graphkeys_clickselect_invoke(bContext *C, wmOperator *op, wmEvent *ev
|
||||
mouse_graph_keys(&ac, mval, selectmode, 0);
|
||||
}
|
||||
|
||||
/* set notifier that things have changed */
|
||||
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH);
|
||||
/* set notifier that keyframe selection (and also channel selection in some cases) has changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_SELECT|ND_ANIMCHAN_SELECT, NULL);
|
||||
|
||||
/* for tweak grab to work */
|
||||
return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH;
|
||||
}
|
||||
|
||||
void GRAPHEDIT_OT_keyframes_clickselect (wmOperatorType *ot)
|
||||
void GRAPH_OT_clickselect (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Mouse Select Keys";
|
||||
ot->idname= "GRAPHEDIT_OT_keyframes_clickselect";
|
||||
ot->idname= "GRAPH_OT_clickselect";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke= graphkeys_clickselect_invoke;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
ot->poll= graphop_visible_keyframes_poll;
|
||||
|
||||
/* id-props */
|
||||
// XXX should we make this into separate operators?
|
||||
|
||||
288
source/blender/editors/space_graph/graph_utils.c
Normal file
288
source/blender/editors/space_graph/graph_utils.c
Normal file
@@ -0,0 +1,288 @@
|
||||
/**
|
||||
* $Id:
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2009 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
*
|
||||
* Contributor(s): Blender Foundation, Joshua Leung
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
|
||||
#include "DNA_anim_types.h"
|
||||
#include "DNA_action_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_screen_types.h"
|
||||
#include "DNA_userdef_types.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_arithb.h"
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_editVert.h"
|
||||
#include "BLI_rand.h"
|
||||
|
||||
#include "BKE_animsys.h"
|
||||
#include "BKE_action.h"
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_curve.h"
|
||||
#include "BKE_customdata.h"
|
||||
#include "BKE_depsgraph.h"
|
||||
#include "BKE_fcurve.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_scene.h"
|
||||
#include "BKE_screen.h"
|
||||
#include "BKE_utildefines.h"
|
||||
|
||||
#include "BIF_gl.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_define.h"
|
||||
|
||||
#include "ED_anim_api.h"
|
||||
#include "ED_keyframing.h"
|
||||
#include "ED_screen.h"
|
||||
#include "ED_types.h"
|
||||
#include "ED_util.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
#include "UI_resources.h"
|
||||
#include "UI_view2d.h"
|
||||
|
||||
#include "graph_intern.h" // own include
|
||||
|
||||
/* ************************************************************** */
|
||||
/* Active F-Curve */
|
||||
|
||||
/* Find 'active' F-Curve. It must be editable, since that's the purpose of these buttons (subject to change).
|
||||
* We return the 'wrapper' since it contains valuable context info (about hierarchy), which will need to be freed
|
||||
* when the caller is done with it.
|
||||
*/
|
||||
bAnimListElem *get_active_fcurve_channel (bAnimContext *ac)
|
||||
{
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
int filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_ACTIVE | ANIMFILTER_CURVESONLY);
|
||||
int items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
|
||||
|
||||
/* We take the first F-Curve only, since some other ones may have had 'active' flag set
|
||||
* if they were from linked data.
|
||||
*/
|
||||
if (items) {
|
||||
bAnimListElem *ale= (bAnimListElem *)anim_data.first;
|
||||
|
||||
/* remove first item from list, then free the rest of the list and return the stored one */
|
||||
BLI_remlink(&anim_data, ale);
|
||||
BLI_freelistN(&anim_data);
|
||||
|
||||
return ale;
|
||||
}
|
||||
|
||||
/* no active F-Curve */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* ************************************************************** */
|
||||
/* Operator Polling Callbacks */
|
||||
|
||||
/* check if any FModifiers to draw controls for - fcm is 'active' modifier
|
||||
* used for the polling callbacks + also for drawing
|
||||
*/
|
||||
short fcurve_needs_draw_fmodifier_controls (FCurve *fcu, FModifier *fcm)
|
||||
{
|
||||
/* don't draw if there aren't any modifiers at all */
|
||||
if (fcu->modifiers.first == NULL)
|
||||
return 0;
|
||||
|
||||
/* if there's an active modifier - don't draw if it doesn't drastically
|
||||
* alter the curve...
|
||||
*/
|
||||
if (fcm) {
|
||||
switch (fcm->type) {
|
||||
/* clearly harmless */
|
||||
case FMODIFIER_TYPE_CYCLES:
|
||||
return 0;
|
||||
|
||||
/* borderline... */
|
||||
case FMODIFIER_TYPE_NOISE:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* if only one modifier - don't draw if it is muted or disabled */
|
||||
if (fcu->modifiers.first == fcu->modifiers.last) {
|
||||
fcm= fcu->modifiers.first;
|
||||
if (fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED))
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if only active modifier - don't draw if it is muted or disabled */
|
||||
if (fcm) {
|
||||
if (fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED))
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if we're still here, this means that there are modifiers with controls to be drawn */
|
||||
// FIXME: what happens if all the modifiers were muted/disabled
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ------------------- */
|
||||
|
||||
/* Check if there are any visible keyframes (for selection tools) */
|
||||
int graphop_visible_keyframes_poll (bContext *C)
|
||||
{
|
||||
bAnimContext ac;
|
||||
bAnimListElem *ale;
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
ScrArea *sa= CTX_wm_area(C);
|
||||
int filter, items;
|
||||
short found = 0;
|
||||
|
||||
/* firstly, check if in Graph Editor */
|
||||
// TODO: also check for region?
|
||||
if ((sa == NULL) || (sa->spacetype != SPACE_IPO))
|
||||
return 0;
|
||||
|
||||
/* try to init Anim-Context stuff ourselves and check */
|
||||
if (ANIM_animdata_get_context(C, &ac) == 0)
|
||||
return 0;
|
||||
|
||||
/* loop over the visible (selection doesn't matter) F-Curves, and see if they're suitable
|
||||
* stopping on the first successful match
|
||||
*/
|
||||
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVESONLY);
|
||||
items = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
|
||||
if (items == 0)
|
||||
return 0;
|
||||
|
||||
for (ale = anim_data.first; ale; ale= ale->next) {
|
||||
FCurve *fcu= (FCurve *)ale->data;
|
||||
FModifier *fcm;
|
||||
|
||||
/* visible curves for selection must fulfull the following criteria:
|
||||
* - it has bezier keyframes
|
||||
* - F-Curve modifiers do not interfere with the result too much
|
||||
* (i.e. the modifier-control drawing check returns false)
|
||||
*/
|
||||
if (fcu->bezt == NULL)
|
||||
continue;
|
||||
fcm= find_active_fmodifier(&fcu->modifiers);
|
||||
|
||||
found= (fcurve_needs_draw_fmodifier_controls(fcu, fcm) == 0);
|
||||
if (found) break;
|
||||
}
|
||||
|
||||
/* cleanup and return findings */
|
||||
BLI_freelistN(&anim_data);
|
||||
return found;
|
||||
}
|
||||
|
||||
/* Check if there are any visible + editable keyframes (for editing tools) */
|
||||
int graphop_editable_keyframes_poll (bContext *C)
|
||||
{
|
||||
bAnimContext ac;
|
||||
bAnimListElem *ale;
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
ScrArea *sa= CTX_wm_area(C);
|
||||
int filter, items;
|
||||
short found = 0;
|
||||
|
||||
/* firstly, check if in Graph Editor */
|
||||
// TODO: also check for region?
|
||||
if ((sa == NULL) || (sa->spacetype != SPACE_IPO))
|
||||
return 0;
|
||||
|
||||
/* try to init Anim-Context stuff ourselves and check */
|
||||
if (ANIM_animdata_get_context(C, &ac) == 0)
|
||||
return 0;
|
||||
|
||||
/* loop over the editable (selected + editable) F-Curves, and see if they're suitable
|
||||
* stopping on the first successful match
|
||||
*/
|
||||
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
|
||||
items = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
|
||||
if (items == 0)
|
||||
return 0;
|
||||
|
||||
for (ale = anim_data.first; ale; ale= ale->next) {
|
||||
FCurve *fcu= (FCurve *)ale->data;
|
||||
FModifier *fcm;
|
||||
|
||||
/* editable curves must fulfull the following criteria:
|
||||
* - it has bezier keyframes
|
||||
* - it must not be protected from editing (this is already checked for with the foredit flag
|
||||
* - F-Curve modifiers do not interfere with the result too much
|
||||
* (i.e. the modifier-control drawing check returns false)
|
||||
*/
|
||||
if (fcu->bezt == NULL)
|
||||
continue;
|
||||
fcm= find_active_fmodifier(&fcu->modifiers);
|
||||
|
||||
found= (fcurve_needs_draw_fmodifier_controls(fcu, fcm) == 0);
|
||||
if (found) break;
|
||||
}
|
||||
|
||||
/* cleanup and return findings */
|
||||
BLI_freelistN(&anim_data);
|
||||
return found;
|
||||
}
|
||||
|
||||
/* has active F-Curve that's editable */
|
||||
int graphop_active_fcurve_poll (bContext *C)
|
||||
{
|
||||
bAnimContext ac;
|
||||
bAnimListElem *ale;
|
||||
ScrArea *sa= CTX_wm_area(C);
|
||||
short has_fcurve= 0;
|
||||
|
||||
/* firstly, check if in Graph Editor */
|
||||
// TODO: also check for region?
|
||||
if ((sa == NULL) || (sa->spacetype != SPACE_IPO))
|
||||
return 0;
|
||||
|
||||
/* try to init Anim-Context stuff ourselves and check */
|
||||
if (ANIM_animdata_get_context(C, &ac) == 0)
|
||||
return 0;
|
||||
|
||||
/* try to get the Active F-Curve */
|
||||
ale= get_active_fcurve_channel(&ac);
|
||||
if (ale == NULL)
|
||||
return 0;
|
||||
|
||||
/* free temp data... */
|
||||
has_fcurve= ((ale->data) && (ale->type == ANIMTYPE_FCURVE));
|
||||
MEM_freeN(ale);
|
||||
|
||||
/* return success */
|
||||
return has_fcurve;
|
||||
}
|
||||
|
||||
/* ************************************************************** */
|
||||
@@ -72,19 +72,19 @@ ARegion *graph_has_buttons_region(ScrArea *sa)
|
||||
if(ar->regiontype==RGN_TYPE_UI)
|
||||
return ar;
|
||||
|
||||
/* add subdiv level; after channel */
|
||||
/* add subdiv level; after main window */
|
||||
for(ar= sa->regionbase.first; ar; ar= ar->next)
|
||||
if(ar->regiontype==RGN_TYPE_CHANNELS)
|
||||
if(ar->regiontype==RGN_TYPE_WINDOW)
|
||||
break;
|
||||
|
||||
/* is error! */
|
||||
if(ar==NULL) return NULL;
|
||||
|
||||
arnew= MEM_callocN(sizeof(ARegion), "buttons for view3d");
|
||||
arnew= MEM_callocN(sizeof(ARegion), "buttons for nla");
|
||||
|
||||
BLI_insertlinkafter(&sa->regionbase, ar, arnew);
|
||||
arnew->regiontype= RGN_TYPE_UI;
|
||||
arnew->alignment= RGN_ALIGN_BOTTOM|RGN_SPLIT_PREV;
|
||||
arnew->alignment= RGN_ALIGN_RIGHT;
|
||||
|
||||
arnew->flag = RGN_FLAG_HIDDEN;
|
||||
|
||||
@@ -117,7 +117,7 @@ static SpaceLink *graph_new(const bContext *C)
|
||||
ar->alignment= RGN_ALIGN_BOTTOM;
|
||||
|
||||
/* channels */
|
||||
ar= MEM_callocN(sizeof(ARegion), "main area for graphedit");
|
||||
ar= MEM_callocN(sizeof(ARegion), "channels area for graphedit");
|
||||
|
||||
BLI_addtail(&sipo->regionbase, ar);
|
||||
ar->regiontype= RGN_TYPE_CHANNELS;
|
||||
@@ -126,11 +126,11 @@ static SpaceLink *graph_new(const bContext *C)
|
||||
ar->v2d.scroll = (V2D_SCROLL_RIGHT|V2D_SCROLL_BOTTOM);
|
||||
|
||||
/* ui buttons */
|
||||
ar= MEM_callocN(sizeof(ARegion), "main area for graphedit");
|
||||
ar= MEM_callocN(sizeof(ARegion), "buttons area for graphedit");
|
||||
|
||||
BLI_addtail(&sipo->regionbase, ar);
|
||||
ar->regiontype= RGN_TYPE_UI;
|
||||
ar->alignment= RGN_ALIGN_TOP|RGN_SPLIT_PREV;
|
||||
ar->alignment= RGN_ALIGN_RIGHT;
|
||||
ar->flag = RGN_FLAG_HIDDEN;
|
||||
|
||||
/* main area */
|
||||
@@ -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;
|
||||
@@ -365,6 +365,9 @@ static void graph_region_listener(ARegion *ar, wmNotifier *wmn)
|
||||
{
|
||||
/* context changes */
|
||||
switch(wmn->category) {
|
||||
case NC_ANIMATION:
|
||||
ED_region_tag_redraw(ar);
|
||||
break;
|
||||
case NC_SCENE:
|
||||
switch(wmn->data) {
|
||||
case ND_OB_ACTIVE:
|
||||
@@ -395,6 +398,9 @@ static void graph_listener(ScrArea *sa, wmNotifier *wmn)
|
||||
{
|
||||
/* context changes */
|
||||
switch (wmn->category) {
|
||||
case NC_ANIMATION:
|
||||
ED_area_tag_refresh(sa);
|
||||
break;
|
||||
case NC_SCENE:
|
||||
/*switch (wmn->data) {
|
||||
case ND_OB_ACTIVE:
|
||||
@@ -566,7 +572,7 @@ void ED_spacetype_ipo(void)
|
||||
/* regions: UI buttons */
|
||||
art= MEM_callocN(sizeof(ARegionType), "spacetype graphedit region");
|
||||
art->regionid = RGN_TYPE_UI;
|
||||
art->minsizey= 200;
|
||||
art->minsizex= 200;
|
||||
art->keymapflag= ED_KEYMAP_UI;
|
||||
art->listener= graph_region_listener;
|
||||
art->init= graph_buttons_area_init;
|
||||
|
||||
426
source/blender/editors/space_nla/nla_buttons.c
Normal file
426
source/blender/editors/space_nla/nla_buttons.c
Normal file
@@ -0,0 +1,426 @@
|
||||
/**
|
||||
* $Id:
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2009 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
*
|
||||
* Contributor(s): Blender Foundation, Joshua Leung
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
|
||||
#include "DNA_anim_types.h"
|
||||
#include "DNA_action_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_screen_types.h"
|
||||
#include "DNA_userdef_types.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_arithb.h"
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_editVert.h"
|
||||
#include "BLI_rand.h"
|
||||
|
||||
#include "BKE_animsys.h"
|
||||
#include "BKE_nla.h"
|
||||
#include "BKE_action.h"
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_curve.h"
|
||||
#include "BKE_customdata.h"
|
||||
#include "BKE_depsgraph.h"
|
||||
#include "BKE_fcurve.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_scene.h"
|
||||
#include "BKE_screen.h"
|
||||
#include "BKE_utildefines.h"
|
||||
|
||||
#include "BIF_gl.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_define.h"
|
||||
|
||||
#include "ED_anim_api.h"
|
||||
#include "ED_keyframing.h"
|
||||
#include "ED_screen.h"
|
||||
#include "ED_types.h"
|
||||
#include "ED_util.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
#include "UI_resources.h"
|
||||
#include "UI_view2d.h"
|
||||
|
||||
#include "nla_intern.h" // own include
|
||||
|
||||
|
||||
/* ******************* nla editor space & buttons ************** */
|
||||
|
||||
#define B_NOP 1
|
||||
#define B_REDR 2
|
||||
|
||||
/* -------------- */
|
||||
|
||||
static void do_nla_region_buttons(bContext *C, void *arg, int event)
|
||||
{
|
||||
//Scene *scene= CTX_data_scene(C);
|
||||
|
||||
switch(event) {
|
||||
|
||||
}
|
||||
|
||||
/* default for now */
|
||||
WM_event_add_notifier(C, NC_SCENE|NC_OBJECT|ND_TRANSFORM, NULL);
|
||||
}
|
||||
|
||||
static int nla_panel_context(const bContext *C, PointerRNA *nlt_ptr, PointerRNA *strip_ptr)
|
||||
{
|
||||
bAnimContext ac;
|
||||
bAnimListElem *ale= NULL;
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
short found=0;
|
||||
int filter;
|
||||
|
||||
/* for now, only draw if we could init the anim-context info (necessary for all animation-related tools)
|
||||
* to work correctly is able to be correctly retrieved. There's no point showing empty panels?
|
||||
*/
|
||||
if (ANIM_animdata_get_context(C, &ac) == 0)
|
||||
return 0;
|
||||
|
||||
/* extract list of active channel(s), of which we should only take the first one (expecting it to be an NLA track) */
|
||||
filter= (ANIMFILTER_VISIBLE|ANIMFILTER_ACTIVE);
|
||||
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
|
||||
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
if (ale->type == ANIMTYPE_NLATRACK) {
|
||||
NlaTrack *nlt= (NlaTrack *)ale->data;
|
||||
|
||||
/* found it, now set the pointers */
|
||||
if (nlt_ptr) {
|
||||
/* NLA-Track pointer */
|
||||
RNA_pointer_create(ale->id, &RNA_NlaTrack, nlt, nlt_ptr);
|
||||
}
|
||||
if (strip_ptr) {
|
||||
/* NLA-Strip pointer */
|
||||
NlaStrip *strip= BKE_nlastrip_find_active(nlt);
|
||||
RNA_pointer_create(ale->id, &RNA_NlaStrip, strip, strip_ptr);
|
||||
}
|
||||
|
||||
found= 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* free temp data */
|
||||
BLI_freelistN(&anim_data);
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int nla_panel_poll(const bContext *C, PanelType *pt)
|
||||
{
|
||||
return nla_panel_context(C, NULL, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int nla_track_panel_poll(const bContext *C, PanelType *pt)
|
||||
{
|
||||
PointerRNA ptr;
|
||||
return (nla_panel_context(C, &ptr, NULL) && (ptr.data != NULL));
|
||||
}
|
||||
|
||||
static int nla_strip_panel_poll(const bContext *C, PanelType *pt)
|
||||
{
|
||||
PointerRNA ptr;
|
||||
return (nla_panel_context(C, NULL, &ptr) && (ptr.data != NULL));
|
||||
}
|
||||
|
||||
static int nla_strip_actclip_panel_poll(const bContext *C, PanelType *pt)
|
||||
{
|
||||
PointerRNA ptr;
|
||||
NlaStrip *strip;
|
||||
|
||||
if (!nla_panel_context(C, NULL, &ptr))
|
||||
return 0;
|
||||
if (ptr.data == NULL)
|
||||
return 0;
|
||||
|
||||
strip= ptr.data;
|
||||
return (strip->type == NLASTRIP_TYPE_CLIP);
|
||||
}
|
||||
|
||||
/* -------------- */
|
||||
|
||||
/* active NLA-Track */
|
||||
static void nla_panel_track (const bContext *C, Panel *pa)
|
||||
{
|
||||
PointerRNA nlt_ptr;
|
||||
uiLayout *layout= pa->layout;
|
||||
uiLayout *row;
|
||||
uiBlock *block;
|
||||
|
||||
/* check context and also validity of pointer */
|
||||
if (!nla_panel_context(C, &nlt_ptr, NULL))
|
||||
return;
|
||||
|
||||
block= uiLayoutGetBlock(layout);
|
||||
uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL);
|
||||
|
||||
/* Info - Active NLA-Context:Track ---------------------- */
|
||||
row= uiLayoutRow(layout, 1);
|
||||
uiItemR(row, NULL, ICON_NLA, &nlt_ptr, "name", 0, 0, 0);
|
||||
}
|
||||
|
||||
/* generic settings for active NLA-Strip */
|
||||
static void nla_panel_properties(const bContext *C, Panel *pa)
|
||||
{
|
||||
PointerRNA strip_ptr;
|
||||
uiLayout *layout= pa->layout;
|
||||
uiLayout *column, *row, *subcol;
|
||||
uiBlock *block;
|
||||
|
||||
if (!nla_panel_context(C, NULL, &strip_ptr))
|
||||
return;
|
||||
|
||||
block= uiLayoutGetBlock(layout);
|
||||
uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL);
|
||||
|
||||
/* Strip Properties ------------------------------------- */
|
||||
/* strip type */
|
||||
row= uiLayoutColumn(layout, 1);
|
||||
uiItemR(row, NULL, ICON_NLA, &strip_ptr, "name", 0, 0, 0); // XXX icon?
|
||||
uiItemR(row, NULL, 0, &strip_ptr, "type", 0, 0, 0);
|
||||
|
||||
/* strip extents */
|
||||
column= uiLayoutColumn(layout, 1);
|
||||
uiItemL(column, "Strip Extents:", 0);
|
||||
uiItemR(column, NULL, 0, &strip_ptr, "start_frame", 0, 0, 0);
|
||||
uiItemR(column, NULL, 0, &strip_ptr, "end_frame", 0, 0, 0);
|
||||
|
||||
/* extrapolation */
|
||||
row= uiLayoutRow(layout, 1);
|
||||
uiItemR(row, NULL, 0, &strip_ptr, "extrapolation", 0, 0, 0);
|
||||
|
||||
/* blending */
|
||||
row= uiLayoutRow(layout, 1);
|
||||
uiItemR(row, NULL, 0, &strip_ptr, "blending", 0, 0, 0);
|
||||
|
||||
/* blend in/out + autoblending
|
||||
* - blend in/out can only be set when autoblending is off
|
||||
*/
|
||||
column= uiLayoutColumn(layout, 1);
|
||||
uiLayoutSetActive(column, RNA_boolean_get(&strip_ptr, "animated_influence")==0);
|
||||
uiItemR(column, NULL, 0, &strip_ptr, "auto_blending", 0, 0, 0); // XXX as toggle?
|
||||
|
||||
subcol= uiLayoutColumn(column, 1);
|
||||
uiLayoutSetActive(subcol, RNA_boolean_get(&strip_ptr, "auto_blending")==0);
|
||||
uiItemR(subcol, NULL, 0, &strip_ptr, "blend_in", 0, 0, 0);
|
||||
uiItemR(subcol, NULL, 0, &strip_ptr, "blend_out", 0, 0, 0);
|
||||
|
||||
/* settings */
|
||||
column= uiLayoutColumn(layout, 1);
|
||||
uiLayoutSetActive(column, !(RNA_boolean_get(&strip_ptr, "animated_influence") || RNA_boolean_get(&strip_ptr, "animated_time")));
|
||||
uiItemL(column, "Playback Settings:", 0);
|
||||
uiItemR(column, NULL, 0, &strip_ptr, "muted", 0, 0, 0);
|
||||
uiItemR(column, NULL, 0, &strip_ptr, "reversed", 0, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
/* action-clip only settings for active NLA-Strip */
|
||||
static void nla_panel_actclip(const bContext *C, Panel *pa)
|
||||
{
|
||||
PointerRNA strip_ptr;
|
||||
uiLayout *layout= pa->layout;
|
||||
uiLayout *column, *row;
|
||||
uiBlock *block;
|
||||
|
||||
/* check context and also validity of pointer */
|
||||
if (!nla_panel_context(C, NULL, &strip_ptr))
|
||||
return;
|
||||
|
||||
block= uiLayoutGetBlock(layout);
|
||||
uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL);
|
||||
|
||||
/* Strip Properties ------------------------------------- */
|
||||
/* action pointer */
|
||||
row= uiLayoutRow(layout, 1);
|
||||
uiItemR(row, NULL, ICON_ACTION, &strip_ptr, "action", 0, 0, 0);
|
||||
|
||||
/* action extents */
|
||||
// XXX custom names were used here (to avoid the prefixes)... probably not necessary in future?
|
||||
column= uiLayoutColumn(layout, 1);
|
||||
uiItemL(column, "Action Extents:", 0);
|
||||
uiItemR(column, "Start Frame", 0, &strip_ptr, "action_start_frame", 0, 0, 0);
|
||||
uiItemR(column, "End Frame", 0, &strip_ptr, "action_end_frame", 0, 0, 0);
|
||||
|
||||
/* action usage */
|
||||
column= uiLayoutColumn(layout, 1);
|
||||
uiLayoutSetActive(column, RNA_boolean_get(&strip_ptr, "animated_time")==0);
|
||||
uiItemL(column, "Playback Settings:", 0);
|
||||
uiItemR(column, NULL, 0, &strip_ptr, "scale", 0, 0, 0);
|
||||
uiItemR(column, NULL, 0, &strip_ptr, "repeat", 0, 0, 0);
|
||||
}
|
||||
|
||||
/* evaluation settings for active NLA-Strip */
|
||||
static void nla_panel_evaluation(const bContext *C, Panel *pa)
|
||||
{
|
||||
PointerRNA strip_ptr;
|
||||
uiLayout *layout= pa->layout;
|
||||
uiLayout *column, *subcolumn;
|
||||
uiBlock *block;
|
||||
|
||||
/* check context and also validity of pointer */
|
||||
if (!nla_panel_context(C, NULL, &strip_ptr))
|
||||
return;
|
||||
|
||||
block= uiLayoutGetBlock(layout);
|
||||
uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL);
|
||||
|
||||
column= uiLayoutColumn(layout, 1);
|
||||
uiItemR(column, NULL, 0, &strip_ptr, "animated_influence", 0, 0, 0);
|
||||
|
||||
subcolumn= uiLayoutColumn(column, 1);
|
||||
uiLayoutSetEnabled(subcolumn, RNA_boolean_get(&strip_ptr, "animated_influence"));
|
||||
uiItemR(subcolumn, NULL, 0, &strip_ptr, "influence", 0, 0, 0);
|
||||
|
||||
|
||||
column= uiLayoutColumn(layout, 1);
|
||||
uiItemR(column, NULL, 0, &strip_ptr, "animated_time", 0, 0, 0);
|
||||
|
||||
subcolumn= uiLayoutColumn(column, 1);
|
||||
uiLayoutSetEnabled(subcolumn, RNA_boolean_get(&strip_ptr, "animated_time"));
|
||||
uiItemR(subcolumn, NULL, 0, &strip_ptr, "strip_time", 0, 0, 0);
|
||||
}
|
||||
|
||||
/* F-Modifiers for active NLA-Strip */
|
||||
static void nla_panel_modifiers(const bContext *C, Panel *pa)
|
||||
{
|
||||
PointerRNA strip_ptr;
|
||||
NlaStrip *strip;
|
||||
FModifier *fcm;
|
||||
uiLayout *col, *row;
|
||||
uiBlock *block;
|
||||
|
||||
/* check context and also validity of pointer */
|
||||
if (!nla_panel_context(C, NULL, &strip_ptr))
|
||||
return;
|
||||
strip= strip_ptr.data;
|
||||
|
||||
block= uiLayoutGetBlock(pa->layout);
|
||||
uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL);
|
||||
|
||||
/* 'add modifier' button at top of panel */
|
||||
{
|
||||
row= uiLayoutRow(pa->layout, 0);
|
||||
block= uiLayoutGetBlock(row);
|
||||
|
||||
// XXX for now, this will be a operator button which calls a temporary 'add modifier' operator
|
||||
// FIXME: we need to set the only-active property so that this will only add modifiers for the active strip (not all selected)
|
||||
uiDefButO(block, BUT, "NLA_OT_fmodifier_add", WM_OP_INVOKE_REGION_WIN, "Add Modifier", 10, 0, 150, 20, "Adds a new F-Modifier for the active NLA Strip");
|
||||
}
|
||||
|
||||
/* draw each modifier */
|
||||
for (fcm= strip->modifiers.first; fcm; fcm= fcm->next) {
|
||||
col= uiLayoutColumn(pa->layout, 1);
|
||||
|
||||
ANIM_uiTemplate_fmodifier_draw(col, strip_ptr.id.data, &strip->modifiers, fcm);
|
||||
}
|
||||
}
|
||||
|
||||
/* ******************* general ******************************** */
|
||||
|
||||
|
||||
void nla_buttons_register(ARegionType *art)
|
||||
{
|
||||
PanelType *pt;
|
||||
|
||||
pt= MEM_callocN(sizeof(PanelType), "spacetype nla panel track");
|
||||
strcpy(pt->idname, "NLA_PT_track");
|
||||
strcpy(pt->label, "Active Track");
|
||||
pt->draw= nla_panel_track;
|
||||
pt->poll= nla_track_panel_poll;
|
||||
BLI_addtail(&art->paneltypes, pt);
|
||||
|
||||
pt= MEM_callocN(sizeof(PanelType), "spacetype nla panel properties");
|
||||
strcpy(pt->idname, "NLA_PT_properties");
|
||||
strcpy(pt->label, "Active Strip");
|
||||
pt->draw= nla_panel_properties;
|
||||
pt->poll= nla_strip_panel_poll;
|
||||
BLI_addtail(&art->paneltypes, pt);
|
||||
|
||||
pt= MEM_callocN(sizeof(PanelType), "spacetype nla panel properties");
|
||||
strcpy(pt->idname, "NLA_PT_actionclip");
|
||||
strcpy(pt->label, "Action Clip");
|
||||
pt->draw= nla_panel_actclip;
|
||||
pt->poll= nla_strip_actclip_panel_poll;
|
||||
BLI_addtail(&art->paneltypes, pt);
|
||||
|
||||
pt= MEM_callocN(sizeof(PanelType), "spacetype nla panel evaluation");
|
||||
strcpy(pt->idname, "NLA_PT_evaluation");
|
||||
strcpy(pt->label, "Evaluation");
|
||||
pt->draw= nla_panel_evaluation;
|
||||
pt->poll= nla_strip_panel_poll;
|
||||
BLI_addtail(&art->paneltypes, pt);
|
||||
|
||||
pt= MEM_callocN(sizeof(PanelType), "spacetype nla panel modifiers");
|
||||
strcpy(pt->idname, "NLA_PT_modifiers");
|
||||
strcpy(pt->label, "Modifiers");
|
||||
pt->draw= nla_panel_modifiers;
|
||||
pt->poll= nla_strip_panel_poll;
|
||||
BLI_addtail(&art->paneltypes, pt);
|
||||
}
|
||||
|
||||
static int nla_properties(bContext *C, wmOperator *op)
|
||||
{
|
||||
ScrArea *sa= CTX_wm_area(C);
|
||||
ARegion *ar= nla_has_buttons_region(sa);
|
||||
|
||||
if(ar) {
|
||||
ar->flag ^= RGN_FLAG_HIDDEN;
|
||||
ar->v2d.flag &= ~V2D_IS_INITIALISED; /* XXX should become hide/unhide api? */
|
||||
|
||||
ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa);
|
||||
ED_area_tag_redraw(sa);
|
||||
}
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void NLA_OT_properties(wmOperatorType *ot)
|
||||
{
|
||||
ot->name= "Properties";
|
||||
ot->idname= "NLA_OT_properties";
|
||||
|
||||
ot->exec= nla_properties;
|
||||
ot->poll= ED_operator_nla_active;
|
||||
|
||||
/* flags */
|
||||
ot->flag= 0;
|
||||
}
|
||||
516
source/blender/editors/space_nla/nla_channels.c
Normal file
516
source/blender/editors/space_nla/nla_channels.c
Normal file
@@ -0,0 +1,516 @@
|
||||
/**
|
||||
* $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 */
|
||||
|
||||
/* ******************** 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 int mouse_nla_channels (bAnimContext *ac, float x, int channel_index, short selectmode)
|
||||
{
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
bAnimListElem *ale;
|
||||
int filter;
|
||||
int notifierFlags = 0;
|
||||
|
||||
/* get the channel that was clicked on */
|
||||
/* filter channels */
|
||||
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 0;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
notifierFlags |= ND_ANIMCHAN_EDIT;
|
||||
}
|
||||
else {
|
||||
/* set selection status */
|
||||
if (selectmode == SELECT_INVERT) {
|
||||
/* swap select */
|
||||
sce->flag ^= SCE_DS_SELECTED;
|
||||
}
|
||||
else {
|
||||
sce->flag |= SCE_DS_SELECTED;
|
||||
}
|
||||
|
||||
notifierFlags |= ND_ANIMCHAN_SELECT;
|
||||
}
|
||||
}
|
||||
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
|
||||
notifierFlags |= ND_ANIMCHAN_EDIT;
|
||||
}
|
||||
else if (nlaedit_is_tweakmode_on(ac) == 0) {
|
||||
/* 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);
|
||||
|
||||
/* notifiers - channel was selected */
|
||||
notifierFlags |= ND_ANIMCHAN_SELECT;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ANIMTYPE_FILLMATD:
|
||||
{
|
||||
Object *ob= (Object *)ale->data;
|
||||
ob->nlaflag ^= OB_ADS_SHOWMATS; // XXX
|
||||
notifierFlags |= ND_ANIMCHAN_EDIT;
|
||||
}
|
||||
break;
|
||||
|
||||
case ANIMTYPE_DSMAT:
|
||||
{
|
||||
Material *ma= (Material *)ale->data;
|
||||
ma->flag ^= MA_DS_EXPAND;
|
||||
notifierFlags |= ND_ANIMCHAN_EDIT;
|
||||
}
|
||||
break;
|
||||
case ANIMTYPE_DSLAM:
|
||||
{
|
||||
Lamp *la= (Lamp *)ale->data;
|
||||
la->flag ^= LA_DS_EXPAND;
|
||||
notifierFlags |= ND_ANIMCHAN_EDIT;
|
||||
}
|
||||
break;
|
||||
case ANIMTYPE_DSCAM:
|
||||
{
|
||||
Camera *ca= (Camera *)ale->data;
|
||||
ca->flag ^= CAM_DS_EXPAND;
|
||||
notifierFlags |= ND_ANIMCHAN_EDIT;
|
||||
}
|
||||
break;
|
||||
case ANIMTYPE_DSCUR:
|
||||
{
|
||||
Curve *cu= (Curve *)ale->data;
|
||||
cu->flag ^= CU_DS_EXPAND;
|
||||
notifierFlags |= ND_ANIMCHAN_EDIT;
|
||||
}
|
||||
break;
|
||||
case ANIMTYPE_DSSKEY:
|
||||
{
|
||||
Key *key= (Key *)ale->data;
|
||||
key->flag ^= KEYBLOCK_DS_EXPAND;
|
||||
notifierFlags |= ND_ANIMCHAN_EDIT;
|
||||
}
|
||||
break;
|
||||
case ANIMTYPE_DSWOR:
|
||||
{
|
||||
World *wo= (World *)ale->data;
|
||||
wo->flag ^= WO_DS_EXPAND;
|
||||
notifierFlags |= ND_ANIMCHAN_EDIT;
|
||||
}
|
||||
break;
|
||||
|
||||
case ANIMTYPE_NLATRACK:
|
||||
{
|
||||
NlaTrack *nlt= (NlaTrack *)ale->data;
|
||||
AnimData *adt= BKE_animdata_from_id(ale->id);
|
||||
short offset;
|
||||
|
||||
/* offset for start of channel (on LHS of channel-list) */
|
||||
if (ale->id) {
|
||||
/* special exception for materials */
|
||||
if (GS(ale->id->name) == ID_MA)
|
||||
offset= 21 + NLACHANNEL_BUTTON_WIDTH;
|
||||
else
|
||||
offset= 14;
|
||||
}
|
||||
else
|
||||
offset= 0;
|
||||
|
||||
if (x >= (NLACHANNEL_NAMEWIDTH-NLACHANNEL_BUTTON_WIDTH)) {
|
||||
/* toggle protection (only if there's a toggle there) */
|
||||
nlt->flag ^= NLATRACK_PROTECTED;
|
||||
|
||||
/* notifier flags - channel was edited */
|
||||
notifierFlags |= ND_ANIMCHAN_EDIT;
|
||||
}
|
||||
else if (x >= (NLACHANNEL_NAMEWIDTH-2*NLACHANNEL_BUTTON_WIDTH)) {
|
||||
/* toggle mute */
|
||||
nlt->flag ^= NLATRACK_MUTED;
|
||||
|
||||
/* notifier flags - channel was edited */
|
||||
notifierFlags |= ND_ANIMCHAN_EDIT;
|
||||
}
|
||||
else if (x <= ((NLACHANNEL_BUTTON_WIDTH*2)+offset)) {
|
||||
/* toggle 'solo' */
|
||||
BKE_nlatrack_solo_toggle(adt, nlt);
|
||||
|
||||
/* notifier flags - channel was edited */
|
||||
notifierFlags |= ND_ANIMCHAN_EDIT;
|
||||
}
|
||||
else if (nlaedit_is_tweakmode_on(ac) == 0) {
|
||||
/* set selection */
|
||||
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, ac->data, ac->datatype, filter, nlt, ANIMTYPE_NLATRACK);
|
||||
|
||||
/* notifier flags - channel was selected */
|
||||
notifierFlags |= ND_ANIMCHAN_SELECT;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ANIMTYPE_NLAACTION:
|
||||
{
|
||||
AnimData *adt= BKE_animdata_from_id(ale->owner); /* this won't crash, right? */
|
||||
|
||||
if (x >= (NLACHANNEL_NAMEWIDTH-NLACHANNEL_BUTTON_WIDTH)) {
|
||||
if (nlaedit_is_tweakmode_on(ac) == 0) {
|
||||
/* 'push-down' action - only usable when not in TweakMode */
|
||||
// TODO: make this use the operator instead of calling the function directly
|
||||
// however, calling the operator requires that we supply the args, and that works with proper buttons only
|
||||
BKE_nla_action_pushdown(adt);
|
||||
}
|
||||
else {
|
||||
/* when in tweakmode, this button becomes the toggle for mapped editing */
|
||||
adt->flag ^= ADT_NLA_EDIT_NOMAP;
|
||||
}
|
||||
|
||||
/* changes to NLA-Action occurred */
|
||||
notifierFlags |= ND_NLA_ACTCHANGE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("Error: Invalid channel type in mouse_nla_channels() \n");
|
||||
}
|
||||
|
||||
/* free channels */
|
||||
BLI_freelistN(&anim_data);
|
||||
|
||||
/* return the notifier-flags set */
|
||||
return notifierFlags;
|
||||
}
|
||||
|
||||
/* ------------------- */
|
||||
|
||||
/* 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;
|
||||
int notifierFlags = 0;
|
||||
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= NLACHANNEL_FIRST, we need to adjust by half a channel's height
|
||||
* so that the tops of channels get caught ok. Since NLACHANNEL_FIRST is really NLACHANNEL_HEIGHT, we simply use
|
||||
* NLACHANNEL_HEIGHT_HALF.
|
||||
*/
|
||||
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 */
|
||||
notifierFlags= mouse_nla_channels(&ac, x, channel_index, selectmode);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|notifierFlags, NULL);
|
||||
|
||||
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_nla_active;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
|
||||
/* id-props */
|
||||
RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); // SHIFTKEY
|
||||
}
|
||||
|
||||
/* *********************************************** */
|
||||
/* Special Operators */
|
||||
|
||||
/* ******************** Add Tracks Operator ***************************** */
|
||||
/* Add NLA Tracks to the same AnimData block as a selected track, or above the selected tracks */
|
||||
|
||||
static int nlaedit_add_tracks_exec (bContext *C, wmOperator *op)
|
||||
{
|
||||
bAnimContext ac;
|
||||
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
bAnimListElem *ale;
|
||||
int filter;
|
||||
|
||||
AnimData *lastAdt = NULL;
|
||||
short above_sel= RNA_boolean_get(op->ptr, "above_selected");
|
||||
|
||||
/* get editor data */
|
||||
if (ANIM_animdata_get_context(C, &ac) == 0)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
/* get a list of the AnimData blocks being shown in the NLA */
|
||||
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_SEL);
|
||||
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
|
||||
|
||||
/* add tracks... */
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
NlaTrack *nlt= (NlaTrack *)ale->data;
|
||||
AnimData *adt= BKE_animdata_from_id(ale->id);
|
||||
|
||||
/* check if just adding a new track above this one,
|
||||
* or whether we're adding a new one to the top of the stack that this one belongs to
|
||||
*/
|
||||
if (above_sel) {
|
||||
/* just add a new one above this one */
|
||||
add_nlatrack(adt, nlt);
|
||||
}
|
||||
else if ((lastAdt == NULL) || (adt != lastAdt)) {
|
||||
/* add one track to the top of the owning AnimData's stack, then don't add anymore to this stack */
|
||||
add_nlatrack(adt, NULL);
|
||||
lastAdt= adt;
|
||||
}
|
||||
}
|
||||
|
||||
/* free temp data */
|
||||
BLI_freelistN(&anim_data);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_EDIT, NULL);
|
||||
|
||||
/* done */
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void NLA_OT_add_tracks (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Add Track(s)";
|
||||
ot->idname= "NLA_OT_add_tracks";
|
||||
ot->description= "Add NLA-Tracks above/after the selected tracks.";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= nlaedit_add_tracks_exec;
|
||||
ot->poll= nlaop_poll_tweakmode_off;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
|
||||
/* properties */
|
||||
RNA_def_boolean(ot->srna, "above_selected", 0, "Above Selected", "Add a new NLA Track above every existing selected one.");
|
||||
}
|
||||
|
||||
/* ******************** Delete Tracks Operator ***************************** */
|
||||
/* Delete selected NLA Tracks */
|
||||
|
||||
static int nlaedit_delete_tracks_exec (bContext *C, wmOperator *op)
|
||||
{
|
||||
bAnimContext ac;
|
||||
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
bAnimListElem *ale;
|
||||
int filter;
|
||||
|
||||
/* get editor data */
|
||||
if (ANIM_animdata_get_context(C, &ac) == 0)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
/* get a list of the AnimData blocks being shown in the NLA */
|
||||
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_SEL);
|
||||
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
|
||||
|
||||
/* delete tracks */
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
NlaTrack *nlt= (NlaTrack *)ale->data;
|
||||
AnimData *adt= BKE_animdata_from_id(ale->id);
|
||||
|
||||
/* call delete on this track - deletes all strips too */
|
||||
free_nlatrack(&adt->nla_tracks, nlt);
|
||||
}
|
||||
|
||||
/* free temp data */
|
||||
BLI_freelistN(&anim_data);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_EDIT, NULL);
|
||||
|
||||
/* done */
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void NLA_OT_delete_tracks (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Delete Tracks";
|
||||
ot->idname= "NLA_OT_delete_tracks";
|
||||
ot->description= "Delete selected NLA-Tracks and the strips they contain.";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= nlaedit_delete_tracks_exec;
|
||||
ot->poll= nlaop_poll_tweakmode_off;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/* *********************************************** */
|
||||
1028
source/blender/editors/space_nla/nla_draw.c
Normal file
1028
source/blender/editors/space_nla/nla_draw.c
Normal file
@@ -0,0 +1,1028 @@
|
||||
/**
|
||||
* $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 <float.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 "DNA_vec_types.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_arithb.h"
|
||||
#include "BLI_rand.h"
|
||||
|
||||
#include "BKE_animsys.h"
|
||||
#include "BKE_fcurve.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_draw.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_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 */
|
||||
|
||||
/* Action-Line ---------------------- */
|
||||
|
||||
/* get colors for drawing Action-Line
|
||||
* NOTE: color returned includes fine-tuned alpha!
|
||||
*/
|
||||
static void nla_action_get_color (AnimData *adt, bAction *act, float color[4])
|
||||
{
|
||||
// TODO: if tweaking some action, use the same color as for the tweaked track (quick hack done for now)
|
||||
if (adt && (adt->flag & ADT_NLA_EDIT_ON)) {
|
||||
// greenish color (same as tweaking strip) - hardcoded for now
|
||||
color[0]= 0.30f;
|
||||
color[1]= 0.95f;
|
||||
color[2]= 0.10f;
|
||||
color[3]= 0.30f;
|
||||
}
|
||||
else {
|
||||
if (act) {
|
||||
// reddish color - hardcoded for now
|
||||
color[0]= 0.8f;
|
||||
color[1]= 0.2f;
|
||||
color[2]= 0.0f;
|
||||
color[3]= 0.4f;
|
||||
}
|
||||
else {
|
||||
// greyish-red color - hardcoded for now
|
||||
color[0]= 0.6f;
|
||||
color[1]= 0.5f;
|
||||
color[2]= 0.5f;
|
||||
color[3]= 0.3f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* draw the keyframes in the specified Action */
|
||||
static void nla_action_draw_keyframes (AnimData *adt, bAction *act, View2D *v2d, float y, float ymin, float ymax)
|
||||
{
|
||||
ListBase keys = {NULL, NULL};
|
||||
ActKeyColumn *ak;
|
||||
float xscale, f1, f2;
|
||||
float color[4];
|
||||
|
||||
/* get a list of the keyframes with NLA-scaling applied */
|
||||
action_to_keylist(adt, act, &keys, NULL);
|
||||
|
||||
if ELEM(NULL, act, keys.first)
|
||||
return;
|
||||
|
||||
/* draw a darkened region behind the strips
|
||||
* - get and reset the background color, this time without the alpha to stand out better
|
||||
*/
|
||||
nla_action_get_color(adt, act, color);
|
||||
glColor3fv(color);
|
||||
/* - draw a rect from the first to the last frame (no extra overlaps for now)
|
||||
* that is slightly stumpier than the track background (hardcoded 2-units here)
|
||||
*/
|
||||
f1= ((ActKeyColumn *)keys.first)->cfra;
|
||||
f2= ((ActKeyColumn *)keys.last)->cfra;
|
||||
|
||||
glRectf(f1, ymin+2, f2, ymax-2);
|
||||
|
||||
|
||||
/* get View2D scaling factor */
|
||||
UI_view2d_getscale(v2d, &xscale, NULL);
|
||||
|
||||
/* for now, color is hardcoded to be black */
|
||||
glColor3f(0.0f, 0.0f, 0.0f);
|
||||
|
||||
/* just draw each keyframe as a simple dot (regardless of the selection status)
|
||||
* - size is 3.0f which is smaller than the editable keyframes, so that there is a distinction
|
||||
*/
|
||||
for (ak= keys.first; ak; ak= ak->next)
|
||||
draw_keyframe_shape(ak->cfra, y, xscale, 3.0f, 0, KEYFRAME_SHAPE_FRAME);
|
||||
|
||||
/* free icons */
|
||||
BLI_freelistN(&keys);
|
||||
}
|
||||
|
||||
/* Strips (Proper) ---------------------- */
|
||||
|
||||
/* get colors for drawing NLA-Strips */
|
||||
static void nla_strip_get_color_inside (AnimData *adt, NlaStrip *strip, float color[3])
|
||||
{
|
||||
if (strip->type == NLASTRIP_TYPE_TRANSITION) {
|
||||
/* Transition Clip */
|
||||
if (strip->flag & NLASTRIP_FLAG_SELECT) {
|
||||
/* selected - use a bright blue color */
|
||||
// FIXME: hardcoded temp-hack colors
|
||||
color[0]= 0.18f;
|
||||
color[1]= 0.46f;
|
||||
color[2]= 0.86f;
|
||||
}
|
||||
else {
|
||||
/* normal, unselected strip - use (hardly noticable) blue tinge */
|
||||
// FIXME: hardcoded temp-hack colors
|
||||
color[0]= 0.11f;
|
||||
color[1]= 0.15f;
|
||||
color[2]= 0.19f;
|
||||
}
|
||||
}
|
||||
else if (strip->type == NLASTRIP_TYPE_META) {
|
||||
/* Meta Clip */
|
||||
// TODO: should temporary metas get different colours too?
|
||||
if (strip->flag & NLASTRIP_FLAG_SELECT) {
|
||||
/* selected - use a bold purple color */
|
||||
// FIXME: hardcoded temp-hack colors
|
||||
color[0]= 0.41f;
|
||||
color[1]= 0.13f;
|
||||
color[2]= 0.59f;
|
||||
}
|
||||
else {
|
||||
/* normal, unselected strip - use (hardly noticable) dark purple tinge */
|
||||
// FIXME: hardcoded temp-hack colors
|
||||
color[0]= 0.20f;
|
||||
color[1]= 0.15f;
|
||||
color[2]= 0.26f;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Action Clip (default/normal type of strip) */
|
||||
if ((strip->flag & NLASTRIP_FLAG_ACTIVE) && (adt && (adt->flag & ADT_NLA_EDIT_ON))) {
|
||||
/* active strip should be drawn green when it is acting as the tweaking strip.
|
||||
* however, this case should be skipped for when not in EditMode...
|
||||
*/
|
||||
// FIXME: hardcoded temp-hack colors
|
||||
color[0]= 0.3f;
|
||||
color[1]= 0.95f;
|
||||
color[2]= 0.1f;
|
||||
}
|
||||
else if (strip->flag & NLASTRIP_FLAG_TWEAKUSER) {
|
||||
/* alert user that this strip is also used by the tweaking track (this is set when going into
|
||||
* 'editmode' for that strip), since the edits made here may not be what the user anticipated
|
||||
*/
|
||||
// FIXME: hardcoded temp-hack colors
|
||||
color[0]= 0.85f;
|
||||
color[1]= 0.0f;
|
||||
color[2]= 0.0f;
|
||||
}
|
||||
else if (strip->flag & NLASTRIP_FLAG_SELECT) {
|
||||
/* selected strip - use theme color for selected */
|
||||
UI_GetThemeColor3fv(TH_STRIP_SELECT, color);
|
||||
}
|
||||
else {
|
||||
/* normal, unselected strip - use standard strip theme color */
|
||||
UI_GetThemeColor3fv(TH_STRIP, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* helper call for drawing influence/time control curves for a given NLA-strip */
|
||||
static void nla_draw_strip_curves (NlaStrip *strip, View2D *v2d, float yminc, float ymaxc)
|
||||
{
|
||||
const float yheight = ymaxc - yminc;
|
||||
|
||||
/* drawing color is simply a light-grey */
|
||||
// TODO: is this color suitable?
|
||||
// XXX nasty hacked color for now... which looks quite bad too...
|
||||
glColor3f(0.7f, 0.7f, 0.7f);
|
||||
|
||||
/* draw with AA'd line, 2 units thick (it's either 1 or 2 px) */
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
glEnable(GL_BLEND);
|
||||
glLineWidth(2.0f);
|
||||
|
||||
/* influence -------------------------- */
|
||||
if (strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) {
|
||||
FCurve *fcu= list_find_fcurve(&strip->fcurves, "influence", 0);
|
||||
float cfra;
|
||||
|
||||
/* plot the curve (over the strip's main region) */
|
||||
glBegin(GL_LINE_STRIP);
|
||||
/* sample at 1 frame intervals, and draw
|
||||
* - min y-val is yminc, max is y-maxc, so clamp in those regions
|
||||
*/
|
||||
for (cfra= strip->start; cfra <= strip->end; cfra += 1.0f) {
|
||||
float y= evaluate_fcurve(fcu, cfra); // assume this to be in 0-1 range
|
||||
glVertex2f(cfra, ((y*yheight)+yminc));
|
||||
}
|
||||
glEnd(); // GL_LINE_STRIP
|
||||
}
|
||||
else {
|
||||
/* use blend in/out values only if both aren't zero */
|
||||
if ((IS_EQ(strip->blendin, 0.0f) && IS_EQ(strip->blendout, 0.0f))==0) {
|
||||
glBegin(GL_LINE_STRIP);
|
||||
/* start of strip - if no blendin, start straight at 1, otherwise from 0 to 1 over blendin frames */
|
||||
if (IS_EQ(strip->blendin, 0.0f) == 0) {
|
||||
glVertex2f(strip->start, yminc);
|
||||
glVertex2f(strip->start + strip->blendin, ymaxc);
|
||||
}
|
||||
else
|
||||
glVertex2f(strip->start, ymaxc);
|
||||
|
||||
/* end of strip */
|
||||
if (IS_EQ(strip->blendout, 0.0f) == 0) {
|
||||
glVertex2f(strip->end - strip->blendout, ymaxc);
|
||||
glVertex2f(strip->end, yminc);
|
||||
}
|
||||
else
|
||||
glVertex2f(strip->end, ymaxc);
|
||||
glEnd(); // GL_LINE_STRIP
|
||||
}
|
||||
}
|
||||
|
||||
/* time -------------------------- */
|
||||
// XXX do we want to draw this curve? in a different colour too?
|
||||
|
||||
/* turn off AA'd lines */
|
||||
glDisable(GL_LINE_SMOOTH);
|
||||
glDisable(GL_BLEND);
|
||||
glLineWidth(1.0f);
|
||||
}
|
||||
|
||||
/* main call for drawing a single NLA-strip */
|
||||
static void nla_draw_strip (AnimData *adt, NlaTrack *nlt, NlaStrip *strip, View2D *v2d, float yminc, float ymaxc)
|
||||
{
|
||||
float color[3];
|
||||
|
||||
/* get color of strip */
|
||||
nla_strip_get_color_inside(adt, strip, color);
|
||||
|
||||
/* draw extrapolation info first (as backdrop) */
|
||||
if (strip->extendmode != NLASTRIP_EXTEND_NOTHING) {
|
||||
/* enable transparency... */
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
switch (strip->extendmode) {
|
||||
/* since this does both sides, only do the 'before' side, and leave the rest to the next case */
|
||||
case NLASTRIP_EXTEND_HOLD:
|
||||
/* only need to draw here if there's no strip before since
|
||||
* it only applies in such a situation
|
||||
*/
|
||||
if (strip->prev == NULL) {
|
||||
/* set the drawing color to the color of the strip, but with very faint alpha */
|
||||
glColor4f(color[0], color[1], color[2], 0.15f);
|
||||
|
||||
/* draw the rect to the edge of the screen */
|
||||
glBegin(GL_QUADS);
|
||||
glVertex2f(v2d->cur.xmin, yminc);
|
||||
glVertex2f(v2d->cur.xmin, ymaxc);
|
||||
glVertex2f(strip->start, ymaxc);
|
||||
glVertex2f(strip->start, yminc);
|
||||
glEnd();
|
||||
}
|
||||
/* no break needed... */
|
||||
|
||||
/* this only draws after the strip */
|
||||
case NLASTRIP_EXTEND_HOLD_FORWARD:
|
||||
/* only need to try and draw if the next strip doesn't occur immediately after */
|
||||
if ((strip->next == NULL) || (IS_EQ(strip->next->start, strip->end)==0)) {
|
||||
/* set the drawing color to the color of the strip, but this time less faint */
|
||||
glColor4f(color[0], color[1], color[2], 0.3f);
|
||||
|
||||
/* draw the rect to the next strip or the edge of the screen */
|
||||
glBegin(GL_QUADS);
|
||||
glVertex2f(strip->end, yminc);
|
||||
glVertex2f(strip->end, ymaxc);
|
||||
|
||||
if (strip->next) {
|
||||
glVertex2f(strip->next->start, ymaxc);
|
||||
glVertex2f(strip->next->start, yminc);
|
||||
}
|
||||
else {
|
||||
glVertex2f(v2d->cur.xmax, ymaxc);
|
||||
glVertex2f(v2d->cur.xmax, yminc);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
/* draw 'inside' of strip itself */
|
||||
glColor3fv(color);
|
||||
uiSetRoundBox(15); /* all corners rounded */
|
||||
gl_round_box_shade(GL_POLYGON, strip->start, yminc, strip->end, ymaxc, 0.0, 0.5, 0.1);
|
||||
|
||||
|
||||
/* draw strip's control 'curves' */
|
||||
nla_draw_strip_curves(strip, v2d, yminc, ymaxc);
|
||||
|
||||
/* draw strip outline
|
||||
* - color used here is to indicate active vs non-active
|
||||
*/
|
||||
if (strip->flag & NLASTRIP_FLAG_ACTIVE) {
|
||||
/* strip should appear 'sunken', so draw a light border around it */
|
||||
glColor3f(0.9f, 1.0f, 0.9f); // FIXME: hardcoded temp-hack colors
|
||||
}
|
||||
else {
|
||||
/* strip should appear to stand out, so draw a dark border around it */
|
||||
glColor3f(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
/* - line style: dotted for muted */
|
||||
if (strip->flag & NLASTRIP_FLAG_MUTED)
|
||||
setlinestyle(4);
|
||||
|
||||
/* draw outline */
|
||||
gl_round_box_shade(GL_LINE_LOOP, strip->start, yminc, strip->end, ymaxc, 0.0, 0.0, 0.1);
|
||||
|
||||
/* if action-clip strip, draw lines delimiting repeats too (in the same color as outline) */
|
||||
if ((strip->type == NLASTRIP_TYPE_CLIP) && IS_EQ(strip->repeat, 1.0f)==0) {
|
||||
float repeatLen = (strip->actend - strip->actstart) * strip->scale;
|
||||
int i;
|
||||
|
||||
/* only draw lines for whole-numbered repeats, starting from the first full-repeat
|
||||
* up to the last full repeat (but not if it lies on the end of the strip)
|
||||
*/
|
||||
for (i = 1; i < strip->repeat; i++) {
|
||||
float repeatPos = strip->start + (repeatLen * i);
|
||||
|
||||
/* don't draw if line would end up on or after the end of the strip */
|
||||
if (repeatPos < strip->end)
|
||||
fdrawline(repeatPos, yminc, repeatPos, ymaxc);
|
||||
}
|
||||
}
|
||||
/* or if meta-strip, draw lines delimiting extents of sub-strips (in same color as outline, if more than 1 exists) */
|
||||
else if ((strip->type == NLASTRIP_TYPE_META) && (strip->strips.first != strip->strips.last)) {
|
||||
NlaStrip *cs;
|
||||
float y= (ymaxc-yminc)/2.0f + yminc;
|
||||
|
||||
/* only draw first-level of child-strips, but don't draw any lines on the endpoints */
|
||||
for (cs= strip->strips.first; cs; cs= cs->next) {
|
||||
/* draw start-line if not same as end of previous (and only if not the first strip)
|
||||
* - on upper half of strip
|
||||
*/
|
||||
if ((cs->prev) && IS_EQ(cs->prev->end, cs->start)==0)
|
||||
fdrawline(cs->start, y, cs->start, ymaxc);
|
||||
|
||||
/* draw end-line if not the last strip
|
||||
* - on lower half of strip
|
||||
*/
|
||||
if (cs->next)
|
||||
fdrawline(cs->end, yminc, cs->end, y);
|
||||
}
|
||||
}
|
||||
|
||||
/* reset linestyle */
|
||||
setlinestyle(0);
|
||||
}
|
||||
|
||||
/* add the relevant text to the cache of text-strings to draw in pixelspace */
|
||||
static void nla_draw_strip_text (NlaTrack *nlt, NlaStrip *strip, int index, View2D *v2d, float yminc, float ymaxc)
|
||||
{
|
||||
char str[256], dir[3];
|
||||
rctf rect;
|
||||
|
||||
/* 'dir' - direction that strip is played in */
|
||||
if (strip->flag & NLASTRIP_FLAG_REVERSE)
|
||||
sprintf(dir, "<-");
|
||||
else
|
||||
sprintf(dir, "->");
|
||||
|
||||
/* just print the name and the range */
|
||||
if (strip->flag & NLASTRIP_FLAG_TEMP_META)
|
||||
sprintf(str, "Temp-Meta | %.2f %s %.2f", strip->start, dir, strip->end);
|
||||
else
|
||||
sprintf(str, "%s | %.2f %s %.2f", strip->name, strip->start, dir, strip->end);
|
||||
|
||||
/* set text colour - if colours (see above) are light, draw black text, otherwise draw white */
|
||||
if (strip->flag & (NLASTRIP_FLAG_ACTIVE|NLASTRIP_FLAG_SELECT|NLASTRIP_FLAG_TWEAKUSER))
|
||||
glColor3f(0.0f, 0.0f, 0.0f);
|
||||
else
|
||||
glColor3f(1.0f, 1.0f, 1.0f);
|
||||
|
||||
/* set bounding-box for text
|
||||
* - padding of 2 'units' on either side
|
||||
*/
|
||||
// TODO: make this centered?
|
||||
rect.xmin= strip->start + 0.5f;
|
||||
rect.ymin= yminc;
|
||||
rect.xmax= strip->end - 0.5f;
|
||||
rect.ymax= ymaxc;
|
||||
|
||||
/* add this string to the cache of texts to draw*/
|
||||
UI_view2d_text_cache_rectf(v2d, &rect, str);
|
||||
}
|
||||
|
||||
/* ---------------------- */
|
||||
|
||||
void draw_nla_main_data (bAnimContext *ac, SpaceNla *snla, ARegion *ar)
|
||||
{
|
||||
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));
|
||||
/* don't use totrect set, as the width stays the same
|
||||
* (NOTE: this is ok here, the configuration is pretty straightforward)
|
||||
*/
|
||||
v2d->tot.ymin= (float)(-height);
|
||||
/* need to do a view-sync here, so that the strips area doesn't jump around */
|
||||
UI_view2d_sync(NULL, ac->sa, v2d, V2D_VIEWSYNC_AREA_VERTICAL);
|
||||
|
||||
/* loop through channels, and set up drawing depending on their type */
|
||||
y= (float)(-NLACHANNEL_HEIGHT);
|
||||
|
||||
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:
|
||||
{
|
||||
AnimData *adt= BKE_animdata_from_id(ale->id);
|
||||
NlaTrack *nlt= (NlaTrack *)ale->data;
|
||||
NlaStrip *strip;
|
||||
int index;
|
||||
|
||||
/* draw each strip in the track (if visible) */
|
||||
for (strip=nlt->strips.first, index=1; strip; strip=strip->next, index++) {
|
||||
if (BKE_nlastrip_within_bounds(strip, v2d->cur.xmin, v2d->cur.xmax)) {
|
||||
/* draw the visualisation of the strip */
|
||||
nla_draw_strip(adt, nlt, strip, v2d, yminc, ymaxc);
|
||||
|
||||
/* add the text for this strip to the cache */
|
||||
nla_draw_strip_text(nlt, strip, index, v2d, yminc, ymaxc);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ANIMTYPE_NLAACTION:
|
||||
{
|
||||
AnimData *adt= BKE_animdata_from_id(ale->id);
|
||||
float color[4];
|
||||
|
||||
/* just draw a semi-shaded rect spanning the width of the viewable area if there's data,
|
||||
* and a second darker rect within which we draw keyframe indicator dots if there's data
|
||||
*/
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
/* get colors for drawing */
|
||||
nla_action_get_color(adt, ale->data, color);
|
||||
glColor4fv(color);
|
||||
|
||||
/* draw slightly shifted up for greater separation from standard channels,
|
||||
* but also slightly shorter for some more contrast when viewing the strips
|
||||
*/
|
||||
glRectf(v2d->cur.xmin, yminc+NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc-NLACHANNEL_SKIP);
|
||||
|
||||
/* draw keyframes in the action */
|
||||
nla_action_draw_keyframes(adt, ale->data, v2d, y, yminc+NLACHANNEL_SKIP, ymaxc-NLACHANNEL_SKIP);
|
||||
|
||||
/* draw 'embossed' lines above and below the strip for effect */
|
||||
/* white base-lines */
|
||||
glLineWidth(2.0f);
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 0.3);
|
||||
fdrawline(v2d->cur.xmin, yminc+NLACHANNEL_SKIP, v2d->cur.xmax, yminc+NLACHANNEL_SKIP);
|
||||
fdrawline(v2d->cur.xmin, ymaxc-NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc-NLACHANNEL_SKIP);
|
||||
|
||||
/* black top-lines */
|
||||
glLineWidth(1.0f);
|
||||
glColor3f(0.0f, 0.0f, 0.0f);
|
||||
fdrawline(v2d->cur.xmin, yminc+NLACHANNEL_SKIP, v2d->cur.xmax, yminc+NLACHANNEL_SKIP);
|
||||
fdrawline(v2d->cur.xmin, ymaxc-NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc-NLACHANNEL_SKIP);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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));
|
||||
/* don't use totrect set, as the width stays the same
|
||||
* (NOTE: this is ok here, the configuration is pretty straightforward)
|
||||
*/
|
||||
v2d->tot.ymin= (float)(-height);
|
||||
|
||||
/* loop through channels, and set up drawing depending on their type */
|
||||
y= (float)(-NLACHANNEL_HEIGHT);
|
||||
|
||||
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_DOWN;
|
||||
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_DOWN;
|
||||
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_DOWN;
|
||||
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_DOWN;
|
||||
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_DOWN;
|
||||
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_DOWN;
|
||||
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_DOWN;
|
||||
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_DOWN;
|
||||
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 this track is active and we're tweaking it, don't draw these toggles */
|
||||
// TODO: need a special macro for this...
|
||||
if ( ((nlt->flag & NLATRACK_ACTIVE) && (nlt->flag & NLATRACK_DISABLED)) == 0 )
|
||||
{
|
||||
if (nlt->flag & NLATRACK_MUTED)
|
||||
mute = ICON_MUTE_IPO_ON;
|
||||
else
|
||||
mute = ICON_MUTE_IPO_OFF;
|
||||
|
||||
if (EDITABLE_NLT(nlt))
|
||||
protect = ICON_UNLOCKED;
|
||||
else
|
||||
protect = ICON_LOCKED;
|
||||
}
|
||||
|
||||
sel = SEL_NLT(nlt);
|
||||
strcpy(name, nlt->name);
|
||||
}
|
||||
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_DOWN)? (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 */
|
||||
AnimData *adt= BKE_animdata_from_id(ale->id);
|
||||
|
||||
// TODO: if tweaking some action, use the same color as for the tweaked track (quick hack done for now)
|
||||
if (adt && (adt->flag & ADT_NLA_EDIT_ON)) {
|
||||
// greenish color (same as tweaking strip) - hardcoded for now
|
||||
glColor3f(0.3f, 0.95f, 0.1f);
|
||||
}
|
||||
else {
|
||||
if (ale->data)
|
||||
glColor3f(0.8f, 0.2f, 0.0f); // reddish color - hardcoded for now
|
||||
else
|
||||
glColor3f(0.6f, 0.5f, 0.5f); // greyish-red color - hardcoded for now
|
||||
}
|
||||
|
||||
offset += 7 * indent;
|
||||
|
||||
/* only on top two corners, to show that this channel sits on top of the preceeding ones */
|
||||
uiSetRoundBox((1|2));
|
||||
|
||||
/* draw slightly shifted up vertically to look like it has more separtion from other channels,
|
||||
* but we then need to slightly shorten it so that it doesn't look like it overlaps
|
||||
*/
|
||||
gl_round_box(GL_POLYGON, x+offset, yminc+NLACHANNEL_SKIP, (float)NLACHANNEL_NAMEWIDTH, ymaxc+NLACHANNEL_SKIP-1, 8);
|
||||
|
||||
/* clear group value, otherwise we cause errors... */
|
||||
group = 0;
|
||||
}
|
||||
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 NLA-action line 'status-icons' - only when there's an action */
|
||||
if ((ale->type == ANIMTYPE_NLAACTION) && (ale->data)) {
|
||||
AnimData *adt= BKE_animdata_from_id(ale->id);
|
||||
|
||||
offset += 16;
|
||||
|
||||
/* now draw some indicator icons */
|
||||
if ((adt) && (adt->flag & ADT_NLA_EDIT_ON)) {
|
||||
/* toggle for tweaking with mapping/no-mapping (i.e. 'in place editing' toggle) */
|
||||
// for now, use pin icon to symbolise this
|
||||
if (adt->flag & ADT_NLA_EDIT_NOMAP)
|
||||
UI_icon_draw((float)(NLACHANNEL_NAMEWIDTH-offset), ydatac, ICON_PINNED);
|
||||
else
|
||||
UI_icon_draw((float)(NLACHANNEL_NAMEWIDTH-offset), ydatac, ICON_UNPINNED);
|
||||
|
||||
fdrawline((float)(NLACHANNEL_NAMEWIDTH-offset), yminc,
|
||||
(float)(NLACHANNEL_NAMEWIDTH-offset), ymaxc);
|
||||
offset += 16;;
|
||||
|
||||
/* 'tweaking action' indicator - not a button */
|
||||
UI_icon_draw((float)NLACHANNEL_NAMEWIDTH-offset, ydatac, ICON_EDIT);
|
||||
}
|
||||
else {
|
||||
/* XXX firstly draw a little rect to help identify that it's different from the toggles */
|
||||
glBegin(GL_LINE_LOOP);
|
||||
glVertex2f((float)NLACHANNEL_NAMEWIDTH-offset-1, y-7);
|
||||
glVertex2f((float)NLACHANNEL_NAMEWIDTH-offset-1, y+9);
|
||||
glVertex2f((float)NLACHANNEL_NAMEWIDTH-1, y+9);
|
||||
glVertex2f((float)NLACHANNEL_NAMEWIDTH-1, y-7);
|
||||
glEnd(); // GL_LINES
|
||||
|
||||
/* 'push down' icon for normal active-actions */
|
||||
UI_icon_draw((float)NLACHANNEL_NAMEWIDTH-offset, ydatac, ICON_FREEZE);
|
||||
}
|
||||
}
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
/* adjust y-position for next one */
|
||||
y -= NLACHANNEL_STEP;
|
||||
}
|
||||
|
||||
/* free tempolary channels */
|
||||
BLI_freelistN(&anim_data);
|
||||
}
|
||||
|
||||
/* *********************************************** */
|
||||
1484
source/blender/editors/space_nla/nla_edit.c
Normal file
1484
source/blender/editors/space_nla/nla_edit.c
Normal file
@@ -0,0 +1,1484 @@
|
||||
/**
|
||||
* $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 <math.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_action.h"
|
||||
#include "BKE_fcurve.h"
|
||||
#include "BKE_nla.h"
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_library.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_report.h"
|
||||
#include "BKE_screen.h"
|
||||
#include "BKE_utildefines.h"
|
||||
|
||||
#include "ED_anim_api.h"
|
||||
#include "ED_keyframes_edit.h"
|
||||
#include "ED_markers.h"
|
||||
#include "ED_space_api.h"
|
||||
#include "ED_screen.h"
|
||||
#include "ED_transform.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_define.h"
|
||||
#include "RNA_enum_types.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
|
||||
#include "nla_private.h" // FIXME... maybe this shouldn't be included?
|
||||
|
||||
/* *********************************************** */
|
||||
/* 'Special' Editing */
|
||||
|
||||
/* ******************** Tweak-Mode Operators ***************************** */
|
||||
/* 'Tweak mode' allows the action referenced by the active NLA-strip to be edited
|
||||
* as if it were the normal Active-Action of its AnimData block.
|
||||
*/
|
||||
|
||||
static int nlaedit_enable_tweakmode_exec (bContext *C, wmOperator *op)
|
||||
{
|
||||
bAnimContext ac;
|
||||
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
bAnimListElem *ale;
|
||||
int filter;
|
||||
int ok=0;
|
||||
|
||||
/* get editor data */
|
||||
if (ANIM_animdata_get_context(C, &ac) == 0)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
/* get a list of the AnimData blocks being shown in the NLA */
|
||||
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_ANIMDATA);
|
||||
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
|
||||
|
||||
/* if no blocks, popup error? */
|
||||
if (anim_data.first == NULL) {
|
||||
BKE_report(op->reports, RPT_ERROR, "No AnimData blocks to enter tweakmode for");
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
/* for each AnimData block with NLA-data, try setting it in tweak-mode */
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
AnimData *adt= ale->data;
|
||||
|
||||
/* try entering tweakmode if valid */
|
||||
ok += BKE_nla_tweakmode_enter(adt);
|
||||
}
|
||||
|
||||
/* free temp data */
|
||||
BLI_freelistN(&anim_data);
|
||||
|
||||
/* if we managed to enter tweakmode on at least one AnimData block,
|
||||
* set the flag for this in the active scene and send notifiers
|
||||
*/
|
||||
if (ac.scene && ok) {
|
||||
/* set editing flag */
|
||||
ac.scene->flag |= SCE_NLA_EDIT_ON;
|
||||
|
||||
/* set notifier that things have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_ACTCHANGE, NULL);
|
||||
}
|
||||
else {
|
||||
BKE_report(op->reports, RPT_ERROR, "No active strip(s) to enter tweakmode on.");
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
/* done */
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void NLA_OT_tweakmode_enter (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Enter Tweak Mode";
|
||||
ot->idname= "NLA_OT_tweakmode_enter";
|
||||
ot->description= "Enter tweaking mode for the action referenced by the active strip.";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= nlaedit_enable_tweakmode_exec;
|
||||
ot->poll= nlaop_poll_tweakmode_off;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/* ------------- */
|
||||
|
||||
static int nlaedit_disable_tweakmode_exec (bContext *C, wmOperator *op)
|
||||
{
|
||||
bAnimContext ac;
|
||||
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
bAnimListElem *ale;
|
||||
int filter;
|
||||
|
||||
/* get editor data */
|
||||
if (ANIM_animdata_get_context(C, &ac) == 0)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
/* get a list of the AnimData blocks being shown in the NLA */
|
||||
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_ANIMDATA);
|
||||
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
|
||||
|
||||
/* if no blocks, popup error? */
|
||||
if (anim_data.first == NULL) {
|
||||
BKE_report(op->reports, RPT_ERROR, "No AnimData blocks to enter tweakmode for");
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
/* for each AnimData block with NLA-data, try exitting tweak-mode */
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
AnimData *adt= ale->data;
|
||||
|
||||
/* try entering tweakmode if valid */
|
||||
BKE_nla_tweakmode_exit(adt);
|
||||
}
|
||||
|
||||
/* free temp data */
|
||||
BLI_freelistN(&anim_data);
|
||||
|
||||
/* if we managed to enter tweakmode on at least one AnimData block,
|
||||
* set the flag for this in the active scene and send notifiers
|
||||
*/
|
||||
if (ac.scene) {
|
||||
/* clear editing flag */
|
||||
ac.scene->flag &= ~SCE_NLA_EDIT_ON;
|
||||
|
||||
/* set notifier that things have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_ACTCHANGE, NULL);
|
||||
}
|
||||
|
||||
/* done */
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void NLA_OT_tweakmode_exit (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Exit Tweak Mode";
|
||||
ot->idname= "NLA_OT_tweakmode_exit";
|
||||
ot->description= "Exit tweaking mode for the action referenced by the active strip.";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= nlaedit_disable_tweakmode_exec;
|
||||
ot->poll= nlaop_poll_tweakmode_on;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/* *********************************************** */
|
||||
/* NLA Editing Operations (Constructive/Destructive) */
|
||||
|
||||
/* ******************** Add Action-Clip Operator ***************************** */
|
||||
/* Add a new Action-Clip strip to the active track (or the active block if no space in the track) */
|
||||
|
||||
/* pop up menu allowing user to choose the action to use */
|
||||
static int nlaedit_add_actionclip_invoke (bContext *C, wmOperator *op, wmEvent *evt)
|
||||
{
|
||||
Main *m= CTX_data_main(C);
|
||||
bAction *act;
|
||||
uiPopupMenu *pup;
|
||||
uiLayout *layout;
|
||||
|
||||
pup= uiPupMenuBegin(C, "Add Action Clip", 0);
|
||||
layout= uiPupMenuLayout(pup);
|
||||
|
||||
/* loop through Actions in Main database, adding as items in the menu */
|
||||
for (act= m->action.first; act; act= act->id.next)
|
||||
uiItemStringO(layout, act->id.name+2, 0, "NLA_OT_add_actionclip", "action", act->id.name);
|
||||
uiItemS(layout);
|
||||
|
||||
uiPupMenuEnd(C, pup);
|
||||
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
/* add the specified action as new strip */
|
||||
static int nlaedit_add_actionclip_exec (bContext *C, wmOperator *op)
|
||||
{
|
||||
bAnimContext ac;
|
||||
Scene *scene;
|
||||
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
bAnimListElem *ale;
|
||||
int filter, items;
|
||||
|
||||
bAction *act = NULL;
|
||||
char actname[22];
|
||||
float cfra;
|
||||
|
||||
/* get editor data */
|
||||
if (ANIM_animdata_get_context(C, &ac) == 0)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
scene= ac.scene;
|
||||
cfra= (float)CFRA;
|
||||
|
||||
/* get action to use */
|
||||
RNA_string_get(op->ptr, "action", actname);
|
||||
act= (bAction *)find_id("AC", actname+2);
|
||||
|
||||
if (act == NULL) {
|
||||
BKE_report(op->reports, RPT_ERROR, "No valid Action to add.");
|
||||
//printf("Add strip - actname = '%s' \n", actname);
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
/* get a list of the editable tracks being shown in the NLA
|
||||
* - this is limited to active ones for now, but could be expanded to
|
||||
*/
|
||||
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_ACTIVE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT);
|
||||
items= ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
|
||||
|
||||
if (items == 0) {
|
||||
BKE_report(op->reports, RPT_ERROR, "No active track(s) to add strip to.");
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
/* for every active track, try to add strip to free space in track or to the top of the stack if no space */
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
NlaTrack *nlt= (NlaTrack *)ale->data;
|
||||
AnimData *adt= BKE_animdata_from_id(ale->id);
|
||||
NlaStrip *strip= NULL;
|
||||
|
||||
/* create a new strip, and offset it to start on the current frame */
|
||||
strip= add_nlastrip(act);
|
||||
|
||||
strip->end += (cfra - strip->start);
|
||||
strip->start = cfra;
|
||||
|
||||
/* firstly try adding strip to our current track, but if that fails, add to a new track */
|
||||
if (BKE_nlatrack_add_strip(nlt, strip) == 0) {
|
||||
/* trying to add to the current failed (no space),
|
||||
* so add a new track to the stack, and add to that...
|
||||
*/
|
||||
nlt= add_nlatrack(adt, NULL);
|
||||
BKE_nlatrack_add_strip(nlt, strip);
|
||||
}
|
||||
|
||||
/* auto-name it */
|
||||
BKE_nlastrip_validate_name(adt, strip);
|
||||
}
|
||||
|
||||
/* free temp data */
|
||||
BLI_freelistN(&anim_data);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_EDIT, NULL);
|
||||
|
||||
/* done */
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void NLA_OT_add_actionclip (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Add Action Strip";
|
||||
ot->idname= "NLA_OT_add_actionclip";
|
||||
ot->description= "Add an Action-Clip strip (i.e. an NLA Strip referencing an Action) to the active track.";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke= nlaedit_add_actionclip_invoke;
|
||||
ot->exec= nlaedit_add_actionclip_exec;
|
||||
ot->poll= nlaop_poll_tweakmode_off;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
|
||||
/* props */
|
||||
// TODO: this would be nicer as an ID-pointer...
|
||||
RNA_def_string(ot->srna, "action", "", 21, "Action", "Name of Action to add as a new Action-Clip Strip.");
|
||||
}
|
||||
|
||||
/* ******************** Add Transition Operator ***************************** */
|
||||
/* Add a new transition strip between selected strips */
|
||||
|
||||
static int nlaedit_add_transition_exec (bContext *C, wmOperator *op)
|
||||
{
|
||||
bAnimContext ac;
|
||||
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
bAnimListElem *ale;
|
||||
int filter;
|
||||
|
||||
int done = 0;
|
||||
|
||||
/* get editor data */
|
||||
if (ANIM_animdata_get_context(C, &ac) == 0)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
/* get a list of the editable tracks being shown in the NLA */
|
||||
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT);
|
||||
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
|
||||
|
||||
/* for each track, find pairs of strips to add transitions to */
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
NlaTrack *nlt= (NlaTrack *)ale->data;
|
||||
AnimData *adt= BKE_animdata_from_id(ale->id);
|
||||
NlaStrip *s1, *s2;
|
||||
|
||||
/* get initial pair of strips */
|
||||
if ELEM(nlt->strips.first, NULL, nlt->strips.last)
|
||||
continue;
|
||||
s1= nlt->strips.first;
|
||||
s2= s1->next;
|
||||
|
||||
/* loop over strips */
|
||||
for (; s1 && s2; s1=s2, s2=s2->next) {
|
||||
NlaStrip *strip;
|
||||
|
||||
/* check if both are selected */
|
||||
if ELEM(0, (s1->flag & NLASTRIP_FLAG_SELECT), (s2->flag & NLASTRIP_FLAG_SELECT))
|
||||
continue;
|
||||
/* check if there's space between the two */
|
||||
if (IS_EQ(s1->end, s2->start))
|
||||
continue;
|
||||
/* make neither one is a transition
|
||||
* - although this is impossible to create with the standard tools,
|
||||
* the user may have altered the settings
|
||||
*/
|
||||
if (ELEM(NLASTRIP_TYPE_TRANSITION, s1->type, s2->type))
|
||||
continue;
|
||||
|
||||
/* allocate new strip */
|
||||
strip= MEM_callocN(sizeof(NlaStrip), "NlaStrip");
|
||||
BLI_insertlinkafter(&nlt->strips, s1, strip);
|
||||
|
||||
/* set the type */
|
||||
strip->type= NLASTRIP_TYPE_TRANSITION;
|
||||
|
||||
/* generic settings
|
||||
* - selected flag to highlight this to the user
|
||||
* - auto-blends to ensure that blend in/out values are automatically
|
||||
* determined by overlaps of strips
|
||||
*/
|
||||
strip->flag = NLASTRIP_FLAG_SELECT|NLASTRIP_FLAG_AUTO_BLENDS;
|
||||
|
||||
/* range is simply defined as the endpoints of the adjacent strips */
|
||||
strip->start = s1->end;
|
||||
strip->end = s2->start;
|
||||
|
||||
/* scale and repeat aren't of any use, but shouldn't ever be 0 */
|
||||
strip->scale= 1.0f;
|
||||
strip->repeat = 1.0f;
|
||||
|
||||
/* auto-name it */
|
||||
BKE_nlastrip_validate_name(adt, strip);
|
||||
|
||||
/* make note of this */
|
||||
done++;
|
||||
}
|
||||
}
|
||||
|
||||
/* free temp data */
|
||||
BLI_freelistN(&anim_data);
|
||||
|
||||
/* was anything added? */
|
||||
if (done) {
|
||||
/* set notifier that things have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_EDIT, NULL);
|
||||
|
||||
/* done */
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
else {
|
||||
BKE_report(op->reports, RPT_ERROR, "Needs at least a pair of adjacent selected strips with a gap between them.");
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
}
|
||||
|
||||
void NLA_OT_add_transition (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Add Transition";
|
||||
ot->idname= "NLA_OT_add_transition";
|
||||
ot->description= "Add a transition strip between two adjacent selected strips.";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= nlaedit_add_transition_exec;
|
||||
ot->poll= nlaop_poll_tweakmode_off;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/* ******************** Add Meta-Strip Operator ***************************** */
|
||||
/* Add new meta-strips incorporating the selected strips */
|
||||
|
||||
/* add the specified action as new strip */
|
||||
static int nlaedit_add_meta_exec (bContext *C, wmOperator *op)
|
||||
{
|
||||
bAnimContext ac;
|
||||
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
bAnimListElem *ale;
|
||||
int filter;
|
||||
|
||||
/* get editor data */
|
||||
if (ANIM_animdata_get_context(C, &ac) == 0)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
/* get a list of the editable tracks being shown in the NLA */
|
||||
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT);
|
||||
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
|
||||
|
||||
/* for each track, find pairs of strips to add transitions to */
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
NlaTrack *nlt= (NlaTrack *)ale->data;
|
||||
AnimData *adt= BKE_animdata_from_id(ale->id);
|
||||
NlaStrip *strip;
|
||||
|
||||
/* create meta-strips from the continuous chains of selected strips */
|
||||
BKE_nlastrips_make_metas(&nlt->strips, 0);
|
||||
|
||||
/* name the metas */
|
||||
for (strip= nlt->strips.first; strip; strip= strip->next) {
|
||||
/* auto-name this strip if selected (that means it is a meta) */
|
||||
if (strip->flag & NLASTRIP_FLAG_SELECT)
|
||||
BKE_nlastrip_validate_name(adt, strip);
|
||||
}
|
||||
}
|
||||
|
||||
/* free temp data */
|
||||
BLI_freelistN(&anim_data);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_EDIT, NULL);
|
||||
|
||||
/* done */
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void NLA_OT_add_meta (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Add Meta-Strips";
|
||||
ot->idname= "NLA_OT_add_meta";
|
||||
ot->description= "Add new meta-strips incorporating the selected strips.";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= nlaedit_add_meta_exec;
|
||||
ot->poll= nlaop_poll_tweakmode_off;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/* ******************** Remove Meta-Strip Operator ***************************** */
|
||||
/* Separate out the strips held by the selected meta-strips */
|
||||
|
||||
static int nlaedit_remove_meta_exec (bContext *C, wmOperator *op)
|
||||
{
|
||||
bAnimContext ac;
|
||||
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
bAnimListElem *ale;
|
||||
int filter;
|
||||
|
||||
/* get editor data */
|
||||
if (ANIM_animdata_get_context(C, &ac) == 0)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
/* get a list of the editable tracks being shown in the NLA */
|
||||
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT);
|
||||
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
|
||||
|
||||
/* for each track, find pairs of strips to add transitions to */
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
NlaTrack *nlt= (NlaTrack *)ale->data;
|
||||
|
||||
/* clear all selected meta-strips, regardless of whether they are temporary or not */
|
||||
BKE_nlastrips_clear_metas(&nlt->strips, 1, 0);
|
||||
}
|
||||
|
||||
/* free temp data */
|
||||
BLI_freelistN(&anim_data);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_EDIT, NULL);
|
||||
|
||||
/* done */
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void NLA_OT_remove_meta (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Remove Meta-Strips";
|
||||
ot->idname= "NLA_OT_remove_meta";
|
||||
ot->description= "Separate out the strips held by the selected meta-strips.";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= nlaedit_remove_meta_exec;
|
||||
ot->poll= nlaop_poll_tweakmode_off;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/* ******************** Duplicate Strips Operator ************************** */
|
||||
/* Duplicates the selected NLA-Strips, putting them on new tracks above the one
|
||||
* the originals were housed in.
|
||||
*/
|
||||
|
||||
static int nlaedit_duplicate_exec (bContext *C, wmOperator *op)
|
||||
{
|
||||
bAnimContext ac;
|
||||
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
bAnimListElem *ale;
|
||||
int filter;
|
||||
|
||||
short done = 0;
|
||||
|
||||
/* get editor data */
|
||||
if (ANIM_animdata_get_context(C, &ac) == 0)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
/* get a list of editable tracks being shown in the NLA */
|
||||
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT);
|
||||
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
|
||||
|
||||
/* duplicate strips in tracks starting from the last one so that we're
|
||||
* less likely to duplicate strips we just duplicated...
|
||||
*/
|
||||
for (ale= anim_data.last; ale; ale= ale->prev) {
|
||||
NlaTrack *nlt= (NlaTrack *)ale->data;
|
||||
AnimData *adt= BKE_animdata_from_id(ale->id);
|
||||
NlaStrip *strip, *nstrip, *next;
|
||||
NlaTrack *track;
|
||||
|
||||
for (strip= nlt->strips.first; strip; strip= next) {
|
||||
next= strip->next;
|
||||
|
||||
/* if selected, split the strip at its midpoint */
|
||||
if (strip->flag & NLASTRIP_FLAG_SELECT) {
|
||||
/* make a copy (assume that this is possible) */
|
||||
nstrip= copy_nlastrip(strip);
|
||||
|
||||
/* in case there's no space in the track above, or we haven't got a reference to it yet, try adding */
|
||||
if (BKE_nlatrack_add_strip(nlt->next, nstrip) == 0) {
|
||||
/* need to add a new track above the one above the current one
|
||||
* - if the current one is the last one, nlt->next will be NULL, which defaults to adding
|
||||
* at the top of the stack anyway...
|
||||
*/
|
||||
track= add_nlatrack(adt, nlt->next);
|
||||
BKE_nlatrack_add_strip(track, nstrip);
|
||||
}
|
||||
|
||||
/* deselect the original and the active flag */
|
||||
strip->flag &= ~(NLASTRIP_FLAG_SELECT|NLASTRIP_FLAG_ACTIVE);
|
||||
|
||||
/* auto-name it */
|
||||
BKE_nlastrip_validate_name(adt, strip);
|
||||
|
||||
done++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* free temp data */
|
||||
BLI_freelistN(&anim_data);
|
||||
|
||||
if (done) {
|
||||
/* set notifier that things have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_EDIT, NULL);
|
||||
|
||||
/* done */
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
else
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
static int nlaedit_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *event)
|
||||
{
|
||||
nlaedit_duplicate_exec(C, op);
|
||||
|
||||
RNA_int_set(op->ptr, "mode", TFM_TIME_TRANSLATE); // XXX
|
||||
WM_operator_name_call(C, "TFM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void NLA_OT_duplicate (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Duplicate Strips";
|
||||
ot->idname= "NLA_OT_duplicate";
|
||||
ot->description= "Duplicate selected NLA-Strips, adding the new strips in new tracks above the originals.";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke= nlaedit_duplicate_invoke;
|
||||
ot->exec= nlaedit_duplicate_exec;
|
||||
ot->poll= nlaop_poll_tweakmode_off;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
|
||||
/* to give to transform */
|
||||
RNA_def_int(ot->srna, "mode", TFM_TRANSLATION, 0, INT_MAX, "Mode", "", 0, INT_MAX);
|
||||
}
|
||||
|
||||
/* ******************** Delete Strips Operator ***************************** */
|
||||
/* Deletes the selected NLA-Strips */
|
||||
|
||||
static int nlaedit_delete_exec (bContext *C, wmOperator *op)
|
||||
{
|
||||
bAnimContext ac;
|
||||
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
bAnimListElem *ale;
|
||||
int filter;
|
||||
|
||||
/* get editor data */
|
||||
if (ANIM_animdata_get_context(C, &ac) == 0)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
/* get a list of the editable tracks being shown in the NLA */
|
||||
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT);
|
||||
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
|
||||
|
||||
/* for each NLA-Track, delete all selected strips */
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
NlaTrack *nlt= (NlaTrack *)ale->data;
|
||||
NlaStrip *strip, *nstrip;
|
||||
|
||||
for (strip= nlt->strips.first; strip; strip= nstrip) {
|
||||
nstrip= strip->next;
|
||||
|
||||
/* if selected, delete */
|
||||
if (strip->flag & NLASTRIP_FLAG_SELECT) {
|
||||
/* if a strip either side of this was a transition, delete those too */
|
||||
if ((strip->prev) && (strip->prev->type == NLASTRIP_TYPE_TRANSITION))
|
||||
free_nlastrip(&nlt->strips, strip->prev);
|
||||
if ((nstrip) && (nstrip->type == NLASTRIP_TYPE_TRANSITION)) {
|
||||
nstrip= nstrip->next;
|
||||
free_nlastrip(&nlt->strips, strip->next);
|
||||
}
|
||||
|
||||
/* finally, delete this strip */
|
||||
free_nlastrip(&nlt->strips, strip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* free temp data */
|
||||
BLI_freelistN(&anim_data);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_EDIT, NULL);
|
||||
|
||||
/* done */
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void NLA_OT_delete (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Delete Strips";
|
||||
ot->idname= "NLA_OT_delete";
|
||||
ot->description= "Delete selected strips.";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= nlaedit_delete_exec;
|
||||
ot->poll= nlaop_poll_tweakmode_off;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/* ******************** Split Strips Operator ***************************** */
|
||||
/* Splits the selected NLA-Strips into two strips at the midpoint of the strip */
|
||||
// TODO's?
|
||||
// - multiple splits
|
||||
// - variable-length splits?
|
||||
|
||||
/* split a given Action-Clip strip */
|
||||
static void nlaedit_split_strip_actclip (AnimData *adt, NlaTrack *nlt, NlaStrip *strip)
|
||||
{
|
||||
NlaStrip *nstrip;
|
||||
float midframe, midaframe, len;
|
||||
|
||||
/* calculate the frames to do the splitting at */
|
||||
/* strip extents */
|
||||
len= strip->end - strip->start;
|
||||
if (IS_EQ(len, 0.0f))
|
||||
return;
|
||||
else
|
||||
midframe= strip->start + (len / 2.0f);
|
||||
|
||||
/* action range */
|
||||
len= strip->actend - strip->actstart;
|
||||
if (IS_EQ(len, 0.0f))
|
||||
midaframe= strip->actend;
|
||||
else
|
||||
midaframe= strip->actstart + (len / 2.0f);
|
||||
|
||||
/* make a copy (assume that this is possible) and append
|
||||
* it immediately after the current strip
|
||||
*/
|
||||
nstrip= copy_nlastrip(strip);
|
||||
BLI_insertlinkafter(&nlt->strips, strip, nstrip);
|
||||
|
||||
/* set the endpoint of the first strip and the start of the new strip
|
||||
* to the midframe values calculated above
|
||||
*/
|
||||
strip->end= midframe;
|
||||
nstrip->start= midframe;
|
||||
|
||||
strip->actend= midaframe;
|
||||
nstrip->actstart= midaframe;
|
||||
|
||||
/* clear the active flag from the copy */
|
||||
nstrip->flag &= ~NLASTRIP_FLAG_ACTIVE;
|
||||
|
||||
/* auto-name the new strip */
|
||||
BKE_nlastrip_validate_name(adt, nstrip);
|
||||
}
|
||||
|
||||
/* split a given Meta strip */
|
||||
static void nlaedit_split_strip_meta (AnimData *adt, NlaTrack *nlt, NlaStrip *strip)
|
||||
{
|
||||
/* simply ungroup it for now... */
|
||||
BKE_nlastrips_clear_metastrip(&nlt->strips, strip);
|
||||
}
|
||||
|
||||
/* ----- */
|
||||
|
||||
static int nlaedit_split_exec (bContext *C, wmOperator *op)
|
||||
{
|
||||
bAnimContext ac;
|
||||
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
bAnimListElem *ale;
|
||||
int filter;
|
||||
|
||||
/* get editor data */
|
||||
if (ANIM_animdata_get_context(C, &ac) == 0)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
/* get a list of editable tracks being shown in the NLA */
|
||||
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT);
|
||||
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
|
||||
|
||||
/* for each NLA-Track, split all selected strips into two strips */
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
NlaTrack *nlt= (NlaTrack *)ale->data;
|
||||
AnimData *adt= BKE_animdata_from_id(ale->id);
|
||||
NlaStrip *strip, *next;
|
||||
|
||||
for (strip= nlt->strips.first; strip; strip= next) {
|
||||
next= strip->next;
|
||||
|
||||
/* if selected, split the strip at its midpoint */
|
||||
if (strip->flag & NLASTRIP_FLAG_SELECT) {
|
||||
/* splitting method depends on the type of strip */
|
||||
switch (strip->type) {
|
||||
case NLASTRIP_TYPE_CLIP: /* action-clip */
|
||||
nlaedit_split_strip_actclip(adt, nlt, strip);
|
||||
break;
|
||||
|
||||
case NLASTRIP_TYPE_META: /* meta-strips need special handling */
|
||||
nlaedit_split_strip_meta(adt, nlt, strip);
|
||||
break;
|
||||
|
||||
default: /* for things like Transitions, do not split! */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* free temp data */
|
||||
BLI_freelistN(&anim_data);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_EDIT, NULL);
|
||||
|
||||
/* done */
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void NLA_OT_split (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Split Strips";
|
||||
ot->idname= "NLA_OT_split";
|
||||
ot->description= "Split selected strips at their midpoints.";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= nlaedit_split_exec;
|
||||
ot->poll= nlaop_poll_tweakmode_off;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/* *********************************************** */
|
||||
/* NLA Editing Operations (Modifying) */
|
||||
|
||||
/* ******************** Toggle Muting Operator ************************** */
|
||||
/* Toggles whether strips are muted or not */
|
||||
|
||||
static int nlaedit_toggle_mute_exec (bContext *C, wmOperator *op)
|
||||
{
|
||||
bAnimContext ac;
|
||||
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
bAnimListElem *ale;
|
||||
int filter;
|
||||
|
||||
/* get editor data */
|
||||
if (ANIM_animdata_get_context(C, &ac) == 0)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
/* get a list of the editable tracks being shown in the NLA */
|
||||
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT);
|
||||
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
|
||||
|
||||
/* go over all selected strips */
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
NlaTrack *nlt= (NlaTrack *)ale->data;
|
||||
NlaStrip *strip;
|
||||
|
||||
/* for every selected strip, toggle muting */
|
||||
for (strip= nlt->strips.first; strip; strip= strip->next) {
|
||||
if (strip->flag & NLASTRIP_FLAG_SELECT) {
|
||||
/* just flip the mute flag for now */
|
||||
// TODO: have a pre-pass to check if mute all or unmute all?
|
||||
strip->flag ^= NLASTRIP_FLAG_MUTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* free temp data */
|
||||
BLI_freelistN(&anim_data);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_EDIT, NULL);
|
||||
|
||||
/* done */
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void NLA_OT_mute_toggle (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Toggle Muting";
|
||||
ot->idname= "NLA_OT_mute_toggle";
|
||||
ot->description= "Mute or un-muted selected strips.";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= nlaedit_toggle_mute_exec;
|
||||
ot->poll= nlaop_poll_tweakmode_off;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/* ******************** Move Strips Up Operator ************************** */
|
||||
/* Tries to move the selected strips into the track above if possible. */
|
||||
|
||||
static int nlaedit_move_up_exec (bContext *C, wmOperator *op)
|
||||
{
|
||||
bAnimContext ac;
|
||||
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
bAnimListElem *ale;
|
||||
int filter;
|
||||
|
||||
/* get editor data */
|
||||
if (ANIM_animdata_get_context(C, &ac) == 0)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
/* get a list of the editable tracks being shown in the NLA */
|
||||
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT);
|
||||
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
|
||||
|
||||
/* since we're potentially moving strips from lower tracks to higher tracks, we should
|
||||
* loop over the tracks in reverse order to avoid moving earlier strips up multiple tracks
|
||||
*/
|
||||
for (ale= anim_data.last; ale; ale= ale->prev) {
|
||||
NlaTrack *nlt= (NlaTrack *)ale->data;
|
||||
NlaTrack *nltn= nlt->next;
|
||||
NlaStrip *strip, *stripn;
|
||||
|
||||
/* if this track has no tracks after it, skip for now... */
|
||||
if (nltn == NULL)
|
||||
continue;
|
||||
|
||||
/* for every selected strip, try to move */
|
||||
for (strip= nlt->strips.first; strip; strip= stripn) {
|
||||
stripn= strip->next;
|
||||
|
||||
if (strip->flag & NLASTRIP_FLAG_SELECT) {
|
||||
/* check if the track above has room for this strip */
|
||||
if (BKE_nlatrack_has_space(nltn, strip->start, strip->end)) {
|
||||
/* remove from its current track, and add to the one above (it 'should' work, so no need to worry) */
|
||||
BLI_remlink(&nlt->strips, strip);
|
||||
BKE_nlatrack_add_strip(nltn, strip);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* free temp data */
|
||||
BLI_freelistN(&anim_data);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_EDIT, NULL);
|
||||
|
||||
/* done */
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void NLA_OT_move_up (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Move Strips Up";
|
||||
ot->idname= "NLA_OT_move_up";
|
||||
ot->description= "Move selected strips up a track if there's room.";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= nlaedit_move_up_exec;
|
||||
ot->poll= nlaop_poll_tweakmode_off;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/* ******************** Move Strips Down Operator ************************** */
|
||||
/* Tries to move the selected strips into the track above if possible. */
|
||||
|
||||
static int nlaedit_move_down_exec (bContext *C, wmOperator *op)
|
||||
{
|
||||
bAnimContext ac;
|
||||
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
bAnimListElem *ale;
|
||||
int filter;
|
||||
|
||||
/* get editor data */
|
||||
if (ANIM_animdata_get_context(C, &ac) == 0)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
/* get a list of the editable tracks being shown in the NLA */
|
||||
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT);
|
||||
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
|
||||
|
||||
/* loop through the tracks in normal order, since we're pushing strips down,
|
||||
* strips won't get operated on twice
|
||||
*/
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
NlaTrack *nlt= (NlaTrack *)ale->data;
|
||||
NlaTrack *nltp= nlt->prev;
|
||||
NlaStrip *strip, *stripn;
|
||||
|
||||
/* if this track has no tracks before it, skip for now... */
|
||||
if (nltp == NULL)
|
||||
continue;
|
||||
|
||||
/* for every selected strip, try to move */
|
||||
for (strip= nlt->strips.first; strip; strip= stripn) {
|
||||
stripn= strip->next;
|
||||
|
||||
if (strip->flag & NLASTRIP_FLAG_SELECT) {
|
||||
/* check if the track below has room for this strip */
|
||||
if (BKE_nlatrack_has_space(nltp, strip->start, strip->end)) {
|
||||
/* remove from its current track, and add to the one above (it 'should' work, so no need to worry) */
|
||||
BLI_remlink(&nlt->strips, strip);
|
||||
BKE_nlatrack_add_strip(nltp, strip);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* free temp data */
|
||||
BLI_freelistN(&anim_data);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_EDIT, NULL);
|
||||
|
||||
/* done */
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void NLA_OT_move_down (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Move Strips Down";
|
||||
ot->idname= "NLA_OT_move_down";
|
||||
ot->description= "Move selected strips down a track if there's room.";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= nlaedit_move_down_exec;
|
||||
ot->poll= nlaop_poll_tweakmode_off;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/* ******************** Apply Scale Operator ***************************** */
|
||||
/* Reset the scaling of the selected strips to 1.0f */
|
||||
|
||||
/* apply scaling to keyframe */
|
||||
static short bezt_apply_nlamapping (BeztEditData *bed, BezTriple *bezt)
|
||||
{
|
||||
/* NLA-strip which has this scaling is stored in bed->data */
|
||||
NlaStrip *strip= (NlaStrip *)bed->data;
|
||||
|
||||
/* adjust all the times */
|
||||
bezt->vec[0][0]= nlastrip_get_frame(strip, bezt->vec[0][0], NLATIME_CONVERT_MAP);
|
||||
bezt->vec[1][0]= nlastrip_get_frame(strip, bezt->vec[1][0], NLATIME_CONVERT_MAP);
|
||||
bezt->vec[2][0]= nlastrip_get_frame(strip, bezt->vec[2][0], NLATIME_CONVERT_MAP);
|
||||
|
||||
/* nothing to return or else we exit */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nlaedit_apply_scale_exec (bContext *C, wmOperator *op)
|
||||
{
|
||||
bAnimContext ac;
|
||||
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
bAnimListElem *ale;
|
||||
int filter;
|
||||
|
||||
BeztEditData bed;
|
||||
|
||||
/* get editor data */
|
||||
if (ANIM_animdata_get_context(C, &ac) == 0)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
/* get a list of the editable tracks being shown in the NLA */
|
||||
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT);
|
||||
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
|
||||
|
||||
/* init the editing data */
|
||||
memset(&bed, 0, sizeof(BeztEditData));
|
||||
|
||||
/* for each NLA-Track, apply scale of all selected strips */
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
NlaTrack *nlt= (NlaTrack *)ale->data;
|
||||
NlaStrip *strip;
|
||||
|
||||
for (strip= nlt->strips.first; strip; strip= strip->next) {
|
||||
/* strip must be selected, and must be action-clip only (transitions don't have scale) */
|
||||
if ((strip->flag & NLASTRIP_FLAG_SELECT) && (strip->type == NLASTRIP_TYPE_CLIP)) {
|
||||
/* if the referenced action is used by other strips, make this strip use its own copy */
|
||||
if (strip->act == NULL)
|
||||
continue;
|
||||
if (strip->act->id.us > 1) {
|
||||
/* make a copy of the Action to work on */
|
||||
bAction *act= copy_action(strip->act);
|
||||
|
||||
/* set this as the new referenced action, decrementing the users of the old one */
|
||||
strip->act->id.us--;
|
||||
strip->act= act;
|
||||
}
|
||||
|
||||
/* setup iterator, and iterate over all the keyframes in the action, applying this scaling */
|
||||
bed.data= strip;
|
||||
ANIM_animchanneldata_keys_bezier_loop(&bed, strip->act, ALE_ACT, NULL, bezt_apply_nlamapping, calchandles_fcurve, 0);
|
||||
|
||||
/* clear scale of strip now that it has been applied,
|
||||
* and recalculate the extents of the action now that it has been scaled
|
||||
* but leave everything else alone
|
||||
*/
|
||||
strip->scale= 1.0f;
|
||||
calc_action_range(strip->act, &strip->actstart, &strip->actend, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* free temp data */
|
||||
BLI_freelistN(&anim_data);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_EDIT, NULL);
|
||||
|
||||
/* done */
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void NLA_OT_apply_scale (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Apply Scale";
|
||||
ot->idname= "NLA_OT_apply_scale";
|
||||
ot->description= "Apply scaling of selected strips to their referenced Actions.";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= nlaedit_apply_scale_exec;
|
||||
ot->poll= nlaop_poll_tweakmode_off;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/* ******************** Clear Scale Operator ***************************** */
|
||||
/* Reset the scaling of the selected strips to 1.0f */
|
||||
|
||||
static int nlaedit_clear_scale_exec (bContext *C, wmOperator *op)
|
||||
{
|
||||
bAnimContext ac;
|
||||
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
bAnimListElem *ale;
|
||||
int filter;
|
||||
|
||||
/* get editor data */
|
||||
if (ANIM_animdata_get_context(C, &ac) == 0)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
/* get a list of the editable tracks being shown in the NLA */
|
||||
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT);
|
||||
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
|
||||
|
||||
/* for each NLA-Track, reset scale of all selected strips */
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
NlaTrack *nlt= (NlaTrack *)ale->data;
|
||||
NlaStrip *strip;
|
||||
|
||||
for (strip= nlt->strips.first; strip; strip= strip->next) {
|
||||
/* strip must be selected, and must be action-clip only (transitions don't have scale) */
|
||||
if ((strip->flag & NLASTRIP_FLAG_SELECT) && (strip->type == NLASTRIP_TYPE_CLIP)) {
|
||||
PointerRNA strip_ptr;
|
||||
|
||||
RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr);
|
||||
RNA_float_set(&strip_ptr, "scale", 1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* free temp data */
|
||||
BLI_freelistN(&anim_data);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_EDIT, NULL);
|
||||
|
||||
/* done */
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void NLA_OT_clear_scale (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Clear Scale";
|
||||
ot->idname= "NLA_OT_clear_scale";
|
||||
ot->description= "Reset scaling of selected strips.";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= nlaedit_clear_scale_exec;
|
||||
ot->poll= nlaop_poll_tweakmode_off;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/* ******************** Snap Strips Operator ************************** */
|
||||
/* Moves the start-point of the selected strips to the specified places */
|
||||
|
||||
/* defines for snap keyframes tool */
|
||||
EnumPropertyItem prop_nlaedit_snap_types[] = {
|
||||
{NLAEDIT_SNAP_CFRA, "CFRA", 0, "Current frame", ""},
|
||||
{NLAEDIT_SNAP_NEAREST_FRAME, "NEAREST_FRAME", 0, "Nearest Frame", ""}, // XXX as single entry?
|
||||
{NLAEDIT_SNAP_NEAREST_SECOND, "NEAREST_SECOND", 0, "Nearest Second", ""}, // XXX as single entry?
|
||||
{NLAEDIT_SNAP_NEAREST_MARKER, "NEAREST_MARKER", 0, "Nearest Marker", ""},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
static int nlaedit_snap_exec (bContext *C, wmOperator *op)
|
||||
{
|
||||
bAnimContext ac;
|
||||
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
bAnimListElem *ale;
|
||||
int filter;
|
||||
|
||||
Scene *scene;
|
||||
int mode = RNA_enum_get(op->ptr, "type");
|
||||
float secf;
|
||||
|
||||
/* get editor data */
|
||||
if (ANIM_animdata_get_context(C, &ac) == 0)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
/* get a list of the editable tracks being shown in the NLA */
|
||||
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT);
|
||||
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
|
||||
|
||||
/* get some necessary vars */
|
||||
scene= ac.scene;
|
||||
secf= (float)FPS;
|
||||
|
||||
/* since we may add tracks, perform this in reverse order */
|
||||
for (ale= anim_data.last; ale; ale= ale->prev) {
|
||||
ListBase tmp_strips = {NULL, NULL};
|
||||
AnimData *adt= BKE_animdata_from_id(ale->id);
|
||||
NlaTrack *nlt= (NlaTrack *)ale->data;
|
||||
NlaStrip *strip, *stripn;
|
||||
NlaTrack *track;
|
||||
|
||||
/* create meta-strips from the continuous chains of selected strips */
|
||||
BKE_nlastrips_make_metas(&nlt->strips, 1);
|
||||
|
||||
/* apply the snapping to all the temp meta-strips, then put them in a separate list to be added
|
||||
* back to the original only if they still fit
|
||||
*/
|
||||
for (strip= nlt->strips.first; strip; strip= stripn) {
|
||||
stripn= strip->next;
|
||||
|
||||
if (strip->flag & NLASTRIP_FLAG_TEMP_META) {
|
||||
float start, end;
|
||||
|
||||
/* get the existing end-points */
|
||||
start= strip->start;
|
||||
end= strip->end;
|
||||
|
||||
/* calculate new start position based on snapping mode */
|
||||
switch (mode) {
|
||||
case NLAEDIT_SNAP_CFRA: /* to current frame */
|
||||
strip->start= (float)CFRA;
|
||||
break;
|
||||
case NLAEDIT_SNAP_NEAREST_FRAME: /* to nearest frame */
|
||||
strip->start= (float)(floor(start+0.5));
|
||||
break;
|
||||
case NLAEDIT_SNAP_NEAREST_SECOND: /* to nearest second */
|
||||
strip->start= ((float)floor(start/secf + 0.5f) * secf);
|
||||
break;
|
||||
case NLAEDIT_SNAP_NEAREST_MARKER: /* to nearest marker */
|
||||
strip->start= (float)ED_markers_find_nearest_marker_time(ac.markers, start);
|
||||
break;
|
||||
default: /* just in case... no snapping */
|
||||
strip->start= start;
|
||||
break;
|
||||
}
|
||||
|
||||
/* get new endpoint based on start-point (and old length) */
|
||||
strip->end= strip->start + (end - start);
|
||||
|
||||
/* apply transforms to meta-strip to its children */
|
||||
BKE_nlameta_flush_transforms(strip);
|
||||
|
||||
/* remove strip from track, and add to the temp buffer */
|
||||
BLI_remlink(&nlt->strips, strip);
|
||||
BLI_addtail(&tmp_strips, strip);
|
||||
}
|
||||
}
|
||||
|
||||
/* try adding each meta-strip back to the track one at a time, to make sure they'll fit */
|
||||
for (strip= tmp_strips.first; strip; strip= stripn) {
|
||||
stripn= strip->next;
|
||||
|
||||
/* remove from temp-strips list */
|
||||
BLI_remlink(&tmp_strips, strip);
|
||||
|
||||
/* in case there's no space in the current track, try adding */
|
||||
if (BKE_nlatrack_add_strip(nlt, strip) == 0) {
|
||||
/* need to add a new track above the current one */
|
||||
track= add_nlatrack(adt, nlt);
|
||||
BKE_nlatrack_add_strip(track, strip);
|
||||
|
||||
/* clear temp meta-strips on this new track, as we may not be able to get back to it */
|
||||
BKE_nlastrips_clear_metas(&track->strips, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* remove the meta-strips now that we're done */
|
||||
BKE_nlastrips_clear_metas(&nlt->strips, 0, 1);
|
||||
}
|
||||
|
||||
/* free temp data */
|
||||
BLI_freelistN(&anim_data);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_EDIT, NULL);
|
||||
|
||||
/* done */
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void NLA_OT_snap (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Snap Strips";
|
||||
ot->idname= "NLA_OT_snap";
|
||||
ot->description= "Move start of strips to specified time.";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke= WM_menu_invoke;
|
||||
ot->exec= nlaedit_snap_exec;
|
||||
ot->poll= nlaop_poll_tweakmode_off;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
|
||||
/* properties */
|
||||
RNA_def_enum(ot->srna, "type", prop_nlaedit_snap_types, 0, "Type", "");
|
||||
}
|
||||
|
||||
/* *********************************************** */
|
||||
/* NLA Modifiers */
|
||||
|
||||
/* ******************** Add F-Modifier Operator *********************** */
|
||||
|
||||
/* present a special customised popup menu for this, with some filtering */
|
||||
static int nla_fmodifier_add_invoke (bContext *C, wmOperator *op, wmEvent *event)
|
||||
{
|
||||
uiPopupMenu *pup;
|
||||
uiLayout *layout;
|
||||
int i;
|
||||
|
||||
pup= uiPupMenuBegin(C, "Add F-Modifier", 0);
|
||||
layout= uiPupMenuLayout(pup);
|
||||
|
||||
/* start from 1 to skip the 'Invalid' modifier type */
|
||||
for (i = 1; i < FMODIFIER_NUM_TYPES; i++) {
|
||||
FModifierTypeInfo *fmi= get_fmodifier_typeinfo(i);
|
||||
|
||||
/* check if modifier is valid for this context */
|
||||
if (fmi == NULL)
|
||||
continue;
|
||||
if (i == FMODIFIER_TYPE_CYCLES) /* we already have repeat... */
|
||||
continue;
|
||||
|
||||
/* add entry to add this type of modifier */
|
||||
uiItemEnumO(layout, fmi->name, 0, "NLA_OT_fmodifier_add", "type", i);
|
||||
}
|
||||
uiItemS(layout);
|
||||
|
||||
uiPupMenuEnd(C, pup);
|
||||
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
static int nla_fmodifier_add_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
bAnimContext ac;
|
||||
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
bAnimListElem *ale;
|
||||
int filter;
|
||||
|
||||
FModifier *fcm;
|
||||
int type= RNA_enum_get(op->ptr, "type");
|
||||
short onlyActive = RNA_boolean_get(op->ptr, "only_active");
|
||||
|
||||
/* get editor data */
|
||||
if (ANIM_animdata_get_context(C, &ac) == 0)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
/* get a list of the editable tracks being shown in the NLA */
|
||||
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT);
|
||||
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
|
||||
|
||||
/* for each NLA-Track, add the specified modifier to all selected strips */
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
NlaTrack *nlt= (NlaTrack *)ale->data;
|
||||
NlaStrip *strip;
|
||||
int i = 1;
|
||||
|
||||
for (strip= nlt->strips.first; strip; strip=strip->next, i++) {
|
||||
/* only add F-Modifier if on active strip? */
|
||||
if ((onlyActive) && (strip->flag & NLASTRIP_FLAG_ACTIVE)==0)
|
||||
continue;
|
||||
|
||||
/* add F-Modifier of specified type to selected, and make it the active one */
|
||||
fcm= add_fmodifier(&strip->modifiers, type);
|
||||
|
||||
if (fcm)
|
||||
set_active_fmodifier(&strip->modifiers, fcm);
|
||||
else {
|
||||
char errormsg[128];
|
||||
sprintf(errormsg, "Modifier couldn't be added to (%s : %d). See console for details.", nlt->name, i);
|
||||
|
||||
BKE_report(op->reports, RPT_ERROR, errormsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* free temp data */
|
||||
BLI_freelistN(&anim_data);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
// FIXME: this doesn't really do it justice...
|
||||
WM_event_add_notifier(C, NC_ANIMATION, NULL);
|
||||
|
||||
/* done */
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void NLA_OT_fmodifier_add (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Add F-Modifier";
|
||||
ot->idname= "NLA_OT_fmodifier_add";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke= nla_fmodifier_add_invoke;
|
||||
ot->exec= nla_fmodifier_add_exec;
|
||||
ot->poll= nlaop_poll_tweakmode_off;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
|
||||
/* id-props */
|
||||
RNA_def_enum(ot->srna, "type", fmodifier_type_items, 0, "Type", "");
|
||||
RNA_def_boolean(ot->srna, "only_active", 0, "Only Active", "Only add F-Modifier of the specified type to the active strip.");
|
||||
}
|
||||
|
||||
/* *********************************************** */
|
||||
@@ -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,19 +41,29 @@
|
||||
#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_markers.h"
|
||||
#include "ED_space_api.h"
|
||||
#include "ED_screen.h"
|
||||
#include "ED_transform.h"
|
||||
|
||||
#include "BIF_gl.h"
|
||||
#include "BIF_glutil.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
#include "UI_resources.h"
|
||||
@@ -57,49 +71,146 @@
|
||||
|
||||
#include "nla_intern.h"
|
||||
|
||||
/* button events */
|
||||
enum {
|
||||
B_REDR = 0,
|
||||
} eActHeader_ButEvents;
|
||||
|
||||
/* ************************ header area region *********************** */
|
||||
|
||||
static void do_viewmenu(bContext *C, void *arg, int event)
|
||||
|
||||
static void nla_viewmenu(bContext *C, uiLayout *layout, void *arg_unused)
|
||||
{
|
||||
bScreen *sc= CTX_wm_screen(C);
|
||||
ScrArea *sa= CTX_wm_area(C);
|
||||
Scene *scene= CTX_data_scene(C);
|
||||
SpaceNla *snla= (SpaceNla*)CTX_wm_space_data(C);
|
||||
PointerRNA spaceptr;
|
||||
|
||||
/* retrieve state */
|
||||
RNA_pointer_create(&sc->id, &RNA_SpaceNLA, snla, &spaceptr);
|
||||
|
||||
/* create menu */
|
||||
uiItemO(layout, NULL, ICON_MENU_PANEL, "NLA_OT_properties");
|
||||
|
||||
uiItemS(layout);
|
||||
|
||||
uiItemR(layout, NULL, 0, &spaceptr, "show_cframe_indicator", 0, 0, 0);
|
||||
|
||||
if (snla->flag & SNLA_DRAWTIME)
|
||||
uiItemO(layout, "Show Frames", 0, "ANIM_OT_time_toggle");
|
||||
else
|
||||
uiItemO(layout, "Show Seconds", 0, "ANIM_OT_time_toggle");
|
||||
|
||||
uiItemS(layout);
|
||||
|
||||
if (scene->flag & SCE_NLA_EDIT_ON)
|
||||
uiItemO(layout, NULL, 0, "NLA_OT_tweakmode_exit");
|
||||
else
|
||||
uiItemO(layout, NULL, 0, "NLA_OT_tweakmode_enter");
|
||||
|
||||
uiItemS(layout);
|
||||
|
||||
uiItemO(layout, NULL, 0, "ANIM_OT_previewrange_set");
|
||||
uiItemO(layout, NULL, 0, "ANIM_OT_previewrange_clear");
|
||||
|
||||
uiItemS(layout);
|
||||
|
||||
//uiItemO(layout, NULL, 0, "NLA_OT_view_all");
|
||||
|
||||
if (sa->full)
|
||||
uiItemO(layout, NULL, 0, "SCREEN_OT_screen_full_area"); // "Tile Window", Ctrl UpArrow
|
||||
else
|
||||
uiItemO(layout, NULL, 0, "SCREEN_OT_screen_full_area"); // "Maximize Window", Ctr DownArrow
|
||||
}
|
||||
|
||||
static uiBlock *dummy_viewmenu(bContext *C, ARegion *ar, void *arg_unused)
|
||||
static void nla_selectmenu(bContext *C, uiLayout *layout, void *arg_unused)
|
||||
{
|
||||
ScrArea *curarea= CTX_wm_area(C);
|
||||
uiBlock *block;
|
||||
short yco= 0, menuwidth=120;
|
||||
uiItemO(layout, NULL, 0, "NLA_OT_select_all_toggle");
|
||||
uiItemBooleanO(layout, "Invert All", 0, "NLA_OT_select_all_toggle", "invert", 1);
|
||||
|
||||
block= uiBeginBlock(C, ar, "dummy_viewmenu", UI_EMBOSSP);
|
||||
uiBlockSetButmFunc(block, do_viewmenu, NULL);
|
||||
uiItemS(layout);
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Nothing yet", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
|
||||
|
||||
if(curarea->headertype==HEADERTOP) {
|
||||
uiBlockSetDirection(block, UI_DOWN);
|
||||
}
|
||||
else {
|
||||
uiBlockSetDirection(block, UI_TOP);
|
||||
uiBlockFlipOrder(block);
|
||||
}
|
||||
|
||||
uiTextBoundsBlock(block, 50);
|
||||
uiEndBlock(C, block);
|
||||
|
||||
return block;
|
||||
uiItemO(layout, NULL, 0, "NLA_OT_select_border");
|
||||
uiItemBooleanO(layout, "Border Axis Range", 0, "NLA_OT_select_border", "axis_range", 1);
|
||||
}
|
||||
|
||||
static void nla_edit_transformmenu(bContext *C, uiLayout *layout, void *arg_unused)
|
||||
{
|
||||
// XXX these operators may change for NLA...
|
||||
uiItemEnumO(layout, "Grab/Move", 0, "TFM_OT_transform", "mode", TFM_TRANSLATION);
|
||||
uiItemEnumO(layout, "Extend", 0, "TFM_OT_transform", "mode", TFM_TIME_EXTEND);
|
||||
uiItemEnumO(layout, "Scale", 0, "TFM_OT_transform", "mode", TFM_TIME_SCALE);
|
||||
}
|
||||
|
||||
static void nla_edit_snapmenu(bContext *C, uiLayout *layout, void *arg_unused)
|
||||
{
|
||||
uiItemEnumO(layout, NULL, 0, "NLA_OT_snap", "type", NLAEDIT_SNAP_CFRA);
|
||||
uiItemEnumO(layout, NULL, 0, "NLA_OT_snap", "type", NLAEDIT_SNAP_NEAREST_FRAME);
|
||||
uiItemEnumO(layout, NULL, 0, "NLA_OT_snap", "type", NLAEDIT_SNAP_NEAREST_SECOND);
|
||||
uiItemEnumO(layout, NULL, 0, "NLA_OT_snap", "type", NLAEDIT_SNAP_NEAREST_MARKER);
|
||||
}
|
||||
|
||||
static void nla_editmenu(bContext *C, uiLayout *layout, void *arg_unused)
|
||||
{
|
||||
uiItemMenuF(layout, "Transform", 0, nla_edit_transformmenu);
|
||||
uiItemMenuF(layout, "Snap", 0, nla_edit_snapmenu);
|
||||
|
||||
uiItemS(layout);
|
||||
|
||||
uiItemO(layout, NULL, 0, "NLA_OT_duplicate");
|
||||
uiItemO(layout, NULL, 0, "NLA_OT_split");
|
||||
|
||||
uiItemS(layout);
|
||||
|
||||
uiItemO(layout, NULL, 0, "NLA_OT_delete");
|
||||
|
||||
uiItemS(layout);
|
||||
|
||||
uiItemO(layout, NULL, 0, "NLA_OT_mute_toggle");
|
||||
|
||||
uiItemS(layout);
|
||||
|
||||
uiItemO(layout, NULL, 0, "NLA_OT_apply_scale");
|
||||
uiItemO(layout, NULL, 0, "NLA_OT_clear_scale");
|
||||
|
||||
uiItemS(layout);
|
||||
|
||||
uiItemO(layout, NULL, 0, "NLA_OT_move_up");
|
||||
uiItemO(layout, NULL, 0, "NLA_OT_move_down");
|
||||
}
|
||||
|
||||
static void nla_addmenu(bContext *C, uiLayout *layout, void *arg_unused)
|
||||
{
|
||||
uiItemO(layout, NULL, 0, "NLA_OT_add_actionclip");
|
||||
uiItemO(layout, NULL, 0, "NLA_OT_add_transition");
|
||||
|
||||
uiItemS(layout);
|
||||
|
||||
uiItemO(layout, NULL, 0, "NLA_OT_add_meta");
|
||||
uiItemO(layout, NULL, 0, "NLA_OT_remove_meta");
|
||||
|
||||
uiItemS(layout);
|
||||
|
||||
uiItemO(layout, NULL, 0, "NLA_OT_add_tracks");
|
||||
uiItemBooleanO(layout, "Add Tracks Above Selected", 0, "NLA_OT_add_tracks", "above_selected", 1);
|
||||
}
|
||||
|
||||
/* ------------------ */
|
||||
|
||||
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,17 +220,68 @@ 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");
|
||||
uiDefPulldownBut(block, dummy_viewmenu, CTX_wm_area(C),
|
||||
"View", xco, yco-2, xmax-3, 24, "");
|
||||
xco+=XIC+xmax;
|
||||
uiDefMenuBut(block, nla_viewmenu, NULL, "View", xco, yco, xmax-3, 20, "");
|
||||
xco+= xmax;
|
||||
|
||||
xmax= GetButStringLength("Select");
|
||||
uiDefMenuBut(block, nla_selectmenu, NULL, "Select", xco, yco, xmax-3, 20, "");
|
||||
xco+= xmax;
|
||||
|
||||
xmax= GetButStringLength("Edit");
|
||||
uiDefMenuBut(block, nla_editmenu, NULL, "Edit", xco, yco, xmax-3, 20, "");
|
||||
xco+= xmax;
|
||||
|
||||
xmax= GetButStringLength("Add");
|
||||
uiDefMenuBut(block, nla_addmenu, NULL, "Add", xco, yco, xmax-3, 20, "");
|
||||
xco+= xmax;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
|
||||
@@ -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,107 @@
|
||||
|
||||
/* internal exports only */
|
||||
|
||||
/* **************************************** */
|
||||
/* Macros, etc. only used by NLA */
|
||||
|
||||
/* **************************************** */
|
||||
/* space_nla.c / nla_buttons.c */
|
||||
|
||||
ARegion *nla_has_buttons_region(ScrArea *sa);
|
||||
|
||||
void nla_buttons_register(ARegionType *art);
|
||||
void NLA_OT_properties(wmOperatorType *ot);
|
||||
|
||||
/* **************************************** */
|
||||
/* 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 NLA_OT_select_all_toggle(wmOperatorType *ot);
|
||||
void NLA_OT_select_border(wmOperatorType *ot);
|
||||
void NLA_OT_click_select(wmOperatorType *ot);
|
||||
|
||||
/* **************************************** */
|
||||
/* nla_edit.c */
|
||||
|
||||
/* defines for snap strips
|
||||
*/
|
||||
enum {
|
||||
NLAEDIT_SNAP_CFRA = 1,
|
||||
NLAEDIT_SNAP_NEAREST_FRAME,
|
||||
NLAEDIT_SNAP_NEAREST_SECOND,
|
||||
NLAEDIT_SNAP_NEAREST_MARKER,
|
||||
} eNlaEdit_Snap_Mode;
|
||||
|
||||
/* --- */
|
||||
|
||||
void NLA_OT_tweakmode_enter(wmOperatorType *ot);
|
||||
void NLA_OT_tweakmode_exit(wmOperatorType *ot);
|
||||
|
||||
/* --- */
|
||||
|
||||
void NLA_OT_add_actionclip(wmOperatorType *ot);
|
||||
void NLA_OT_add_transition(wmOperatorType *ot);
|
||||
|
||||
void NLA_OT_add_meta(wmOperatorType *ot);
|
||||
void NLA_OT_remove_meta(wmOperatorType *ot);
|
||||
|
||||
void NLA_OT_duplicate(wmOperatorType *ot);
|
||||
void NLA_OT_delete(wmOperatorType *ot);
|
||||
void NLA_OT_split(wmOperatorType *ot);
|
||||
|
||||
void NLA_OT_mute_toggle(wmOperatorType *ot);
|
||||
|
||||
void NLA_OT_move_up(wmOperatorType *ot);
|
||||
void NLA_OT_move_down(wmOperatorType *ot);
|
||||
|
||||
void NLA_OT_apply_scale(wmOperatorType *ot);
|
||||
void NLA_OT_clear_scale(wmOperatorType *ot);
|
||||
|
||||
void NLA_OT_snap(wmOperatorType *ot);
|
||||
|
||||
void NLA_OT_fmodifier_add(wmOperatorType *ot);
|
||||
|
||||
|
||||
/* **************************************** */
|
||||
/* nla_channels.c */
|
||||
|
||||
void NLA_OT_channels_click(wmOperatorType *ot);
|
||||
|
||||
void NLA_OT_add_tracks(wmOperatorType *ot);
|
||||
void NLA_OT_delete_tracks(wmOperatorType *ot);
|
||||
|
||||
/* **************************************** */
|
||||
/* nla_ops.c */
|
||||
|
||||
int nlaop_poll_tweakmode_off(bContext *C);
|
||||
int nlaop_poll_tweakmode_on (bContext *C);
|
||||
|
||||
short nlaedit_is_tweakmode_on(bAnimContext *ac);
|
||||
|
||||
/* --- */
|
||||
|
||||
void nla_operatortypes(void);
|
||||
void nla_keymap(wmWindowManager *wm);
|
||||
|
||||
#endif /* ED_NLA_INTERN_H */
|
||||
|
||||
|
||||
307
source/blender/editors/space_nla/nla_ops.c
Normal file
307
source/blender/editors/space_nla/nla_ops.c
Normal file
@@ -0,0 +1,307 @@
|
||||
/**
|
||||
* $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 "ED_transform.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
|
||||
|
||||
/* ************************** poll callbacks for operators **********************************/
|
||||
|
||||
/* tweakmode is NOT enabled */
|
||||
int nlaop_poll_tweakmode_off (bContext *C)
|
||||
{
|
||||
Scene *scene;
|
||||
|
||||
/* for now, we check 2 things:
|
||||
* 1) active editor must be NLA
|
||||
* 2) tweakmode is currently set as a 'per-scene' flag
|
||||
* so that it will affect entire NLA data-sets,
|
||||
* but not all AnimData blocks will be in tweakmode for
|
||||
* various reasons
|
||||
*/
|
||||
if (ED_operator_nla_active(C) == 0)
|
||||
return 0;
|
||||
|
||||
scene= CTX_data_scene(C);
|
||||
if ((scene == NULL) || (scene->flag & SCE_NLA_EDIT_ON))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* tweakmode IS enabled */
|
||||
int nlaop_poll_tweakmode_on (bContext *C)
|
||||
{
|
||||
Scene *scene;
|
||||
|
||||
/* for now, we check 2 things:
|
||||
* 1) active editor must be NLA
|
||||
* 2) tweakmode is currently set as a 'per-scene' flag
|
||||
* so that it will affect entire NLA data-sets,
|
||||
* but not all AnimData blocks will be in tweakmode for
|
||||
* various reasons
|
||||
*/
|
||||
if (ED_operator_nla_active(C) == 0)
|
||||
return 0;
|
||||
|
||||
scene= CTX_data_scene(C);
|
||||
if ((scene == NULL) || !(scene->flag & SCE_NLA_EDIT_ON))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* is tweakmode enabled - for use in NLA operator code */
|
||||
short nlaedit_is_tweakmode_on (bAnimContext *ac)
|
||||
{
|
||||
if (ac && ac->scene)
|
||||
return (ac->scene->flag & SCE_NLA_EDIT_ON);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ************************** registration - operator types **********************************/
|
||||
|
||||
void nla_operatortypes(void)
|
||||
{
|
||||
/* view */
|
||||
WM_operatortype_append(NLA_OT_properties);
|
||||
|
||||
/* channels */
|
||||
WM_operatortype_append(NLA_OT_channels_click);
|
||||
|
||||
WM_operatortype_append(NLA_OT_add_tracks);
|
||||
WM_operatortype_append(NLA_OT_delete_tracks);
|
||||
|
||||
/* select */
|
||||
WM_operatortype_append(NLA_OT_click_select);
|
||||
WM_operatortype_append(NLA_OT_select_border);
|
||||
WM_operatortype_append(NLA_OT_select_all_toggle);
|
||||
|
||||
/* edit */
|
||||
WM_operatortype_append(NLA_OT_tweakmode_enter);
|
||||
WM_operatortype_append(NLA_OT_tweakmode_exit);
|
||||
|
||||
WM_operatortype_append(NLA_OT_add_actionclip);
|
||||
WM_operatortype_append(NLA_OT_add_transition);
|
||||
|
||||
WM_operatortype_append(NLA_OT_add_meta);
|
||||
WM_operatortype_append(NLA_OT_remove_meta);
|
||||
|
||||
WM_operatortype_append(NLA_OT_duplicate);
|
||||
WM_operatortype_append(NLA_OT_delete);
|
||||
WM_operatortype_append(NLA_OT_split);
|
||||
|
||||
WM_operatortype_append(NLA_OT_mute_toggle);
|
||||
|
||||
WM_operatortype_append(NLA_OT_move_up);
|
||||
WM_operatortype_append(NLA_OT_move_down);
|
||||
|
||||
WM_operatortype_append(NLA_OT_apply_scale);
|
||||
WM_operatortype_append(NLA_OT_clear_scale);
|
||||
|
||||
WM_operatortype_append(NLA_OT_snap);
|
||||
|
||||
WM_operatortype_append(NLA_OT_fmodifier_add);
|
||||
}
|
||||
|
||||
/* ************************** 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);
|
||||
|
||||
/* channel operations */
|
||||
/* add tracks */
|
||||
WM_keymap_add_item(keymap, "NLA_OT_add_tracks", AKEY, KM_PRESS, KM_SHIFT, 0);
|
||||
RNA_boolean_set(WM_keymap_add_item(keymap, "NLA_OT_add_tracks", AKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0)->ptr, "above_selected", 1);
|
||||
|
||||
/* delete tracks */
|
||||
WM_keymap_add_item(keymap, "NLA_OT_delete_tracks", XKEY, KM_PRESS, 0, 0);
|
||||
WM_keymap_add_item(keymap, "NLA_OT_delete_tracks", DELKEY, KM_PRESS, 0, 0);
|
||||
|
||||
/* General Animation Channels keymap (see anim_channels.c) ----------------------- */
|
||||
/* selection */
|
||||
/* borderselect - not in tweakmode */
|
||||
WM_keymap_add_item(keymap, "ANIM_OT_channels_select_border", BKEY, KM_PRESS, 0, 0);
|
||||
|
||||
/* deselect all - not in tweakmode */
|
||||
WM_keymap_add_item(keymap, "ANIM_OT_channels_select_all_toggle", AKEY, KM_PRESS, 0, 0);
|
||||
RNA_boolean_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_select_all_toggle", IKEY, KM_PRESS, KM_CTRL, 0)->ptr, "invert", 1);
|
||||
|
||||
/* 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, "NLA_OT_click_select", SELECTMOUSE, KM_PRESS, 0, 0);
|
||||
kmi= WM_keymap_add_item(keymap, "NLA_OT_click_select", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0);
|
||||
RNA_boolean_set(kmi->ptr, "extend", 1);
|
||||
kmi= WM_keymap_add_item(keymap, "NLA_OT_click_select", SELECTMOUSE, KM_PRESS, KM_CTRL, 0);
|
||||
RNA_enum_set(kmi->ptr, "left_right", NLAEDIT_LRSEL_TEST);
|
||||
|
||||
/* deselect all */
|
||||
WM_keymap_add_item(keymap, "NLA_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0);
|
||||
RNA_boolean_set(WM_keymap_add_item(keymap, "NLA_OT_select_all_toggle", IKEY, KM_PRESS, KM_CTRL, 0)->ptr, "invert", 1);
|
||||
|
||||
/* borderselect */
|
||||
WM_keymap_add_item(keymap, "NLA_OT_select_border", BKEY, KM_PRESS, 0, 0);
|
||||
RNA_boolean_set(WM_keymap_add_item(keymap, "NLA_OT_select_border", BKEY, KM_PRESS, KM_ALT, 0)->ptr, "axis_range", 1);
|
||||
|
||||
|
||||
/* editing */
|
||||
/* tweakmode
|
||||
* - enter and exit are separate operators with the same hotkey...
|
||||
* This works as they use different poll()'s
|
||||
*/
|
||||
WM_keymap_add_item(keymap, "NLA_OT_tweakmode_enter", TABKEY, KM_PRESS, 0, 0);
|
||||
WM_keymap_add_item(keymap, "NLA_OT_tweakmode_exit", TABKEY, KM_PRESS, 0, 0);
|
||||
|
||||
/* add strips */
|
||||
WM_keymap_add_item(keymap, "NLA_OT_add_actionclip", AKEY, KM_PRESS, KM_SHIFT, 0);
|
||||
WM_keymap_add_item(keymap, "NLA_OT_add_transition", TKEY, KM_PRESS, KM_SHIFT, 0);
|
||||
|
||||
/* meta-strips */
|
||||
WM_keymap_add_item(keymap, "NLA_OT_add_meta", GKEY, KM_PRESS, KM_SHIFT, 0);
|
||||
WM_keymap_add_item(keymap, "NLA_OT_remove_meta", GKEY, KM_PRESS, KM_ALT, 0);
|
||||
|
||||
/* duplicate */
|
||||
WM_keymap_add_item(keymap, "NLA_OT_duplicate", DKEY, KM_PRESS, KM_SHIFT, 0);
|
||||
|
||||
/* delete */
|
||||
WM_keymap_add_item(keymap, "NLA_OT_delete", XKEY, KM_PRESS, 0, 0);
|
||||
WM_keymap_add_item(keymap, "NLA_OT_delete", DELKEY, KM_PRESS, 0, 0);
|
||||
|
||||
/* split */
|
||||
WM_keymap_add_item(keymap, "NLA_OT_split", YKEY, KM_PRESS, 0, 0);
|
||||
|
||||
/* toggles */
|
||||
WM_keymap_add_item(keymap, "NLA_OT_mute_toggle", HKEY, KM_PRESS, 0, 0);
|
||||
|
||||
/* move up */
|
||||
WM_keymap_add_item(keymap, "NLA_OT_move_up", PAGEUPKEY, KM_PRESS, 0, 0);
|
||||
/* move down */
|
||||
WM_keymap_add_item(keymap, "NLA_OT_move_down", PAGEDOWNKEY, KM_PRESS, 0, 0);
|
||||
|
||||
/* apply scale */
|
||||
WM_keymap_add_item(keymap, "NLA_OT_apply_scale", AKEY, KM_PRESS, KM_CTRL, 0);
|
||||
/* clear scale */
|
||||
WM_keymap_add_item(keymap, "NLA_OT_clear_scale", SKEY, KM_PRESS, KM_ALT, 0);
|
||||
|
||||
/* snap */
|
||||
WM_keymap_add_item(keymap, "NLA_OT_snap", SKEY, KM_PRESS, KM_SHIFT, 0);
|
||||
|
||||
/* add f-modifier */
|
||||
WM_keymap_add_item(keymap, "NLA_OT_fmodifier_add", MKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0);
|
||||
|
||||
/* transform system */
|
||||
transform_keymap_for_space(wm, keymap, SPACE_NLA);
|
||||
}
|
||||
|
||||
/* --------------- */
|
||||
|
||||
void nla_keymap(wmWindowManager *wm)
|
||||
{
|
||||
ListBase *keymap;
|
||||
|
||||
/* keymap for all regions */
|
||||
keymap= WM_keymap_listbase(wm, "NLA Generic", SPACE_NLA, 0);
|
||||
WM_keymap_add_item(keymap, "NLA_OT_properties", NKEY, KM_PRESS, 0, 0);
|
||||
|
||||
/* channels */
|
||||
/* Channels are not directly handled by the NLA Editor module, but are inherited from the Animation module.
|
||||
* 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);
|
||||
}
|
||||
|
||||
614
source/blender/editors/space_nla/nla_select.c
Normal file
614
source/blender/editors/space_nla/nla_select.c
Normal file
@@ -0,0 +1,614 @@
|
||||
/**
|
||||
* $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...
|
||||
*/
|
||||
|
||||
enum {
|
||||
DESELECT_STRIPS_NOTEST = 0,
|
||||
DESELECT_STRIPS_TEST,
|
||||
DESELECT_STRIPS_CLEARACTIVE,
|
||||
} eDeselectNlaStrips;
|
||||
|
||||
/* Deselects strips in the NLA Editor
|
||||
* - This is called by the deselect all operator, as well as other ones!
|
||||
*
|
||||
* - test: check if select or deselect all (1) or clear all active (2)
|
||||
* - 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 */
|
||||
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS);
|
||||
|
||||
/* filter data */
|
||||
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
|
||||
|
||||
/* See if we should be selecting or deselecting */
|
||||
if (test == DESELECT_STRIPS_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 */
|
||||
if (test != DESELECT_STRIPS_CLEARACTIVE)
|
||||
ACHANNEL_SET_FLAG(strip, smode, NLASTRIP_FLAG_SELECT);
|
||||
|
||||
/* clear active flag */
|
||||
// TODO: for clear active, do we want to limit this to only doing this on a certain set of tracks though?
|
||||
strip->flag &= ~NLASTRIP_FLAG_ACTIVE;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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, DESELECT_STRIPS_NOTEST, SELECT_INVERT);
|
||||
else
|
||||
deselect_nla_strips(&ac, DESELECT_STRIPS_TEST, SELECT_ADD);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_SELECT, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void NLA_OT_select_all_toggle (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Select All";
|
||||
ot->idname= "NLA_OT_select_all_toggle";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= nlaedit_deselectall_exec;
|
||||
ot->poll= nlaop_poll_tweakmode_off;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
|
||||
|
||||
/* props */
|
||||
RNA_def_boolean(ot->srna, "invert", 0, "Invert", "");
|
||||
}
|
||||
|
||||
/* ******************** Border Select Operator **************************** */
|
||||
/* This operator currently works in one of three ways:
|
||||
* -> BKEY - 1) all strips within region are selected (ACTKEYS_BORDERSEL_ALLSTRIPS)
|
||||
* -> ALT-BKEY - depending on which axis of the region was larger...
|
||||
* -> 2) x-axis, so select all frames within frame range (ACTKEYS_BORDERSEL_FRAMERANGE)
|
||||
* -> 3) y-axis, so select all frames within channels that region included (ACTKEYS_BORDERSEL_CHANNELS)
|
||||
*/
|
||||
|
||||
/* defines for borderselect mode */
|
||||
enum {
|
||||
NLA_BORDERSEL_ALLSTRIPS = 0,
|
||||
NLA_BORDERSEL_FRAMERANGE,
|
||||
NLA_BORDERSEL_CHANNELS,
|
||||
} eActKeys_BorderSelect_Mode;
|
||||
|
||||
|
||||
static void borderselect_nla_strips (bAnimContext *ac, rcti rect, short mode, short selectmode)
|
||||
{
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
bAnimListElem *ale;
|
||||
int filter;
|
||||
|
||||
View2D *v2d= &ac->ar->v2d;
|
||||
rctf rectf;
|
||||
float ymin=(float)(-NLACHANNEL_HEIGHT), ymax=0;
|
||||
|
||||
/* convert border-region to view coordinates */
|
||||
UI_view2d_region_to_view(v2d, rect.xmin, rect.ymin+2, &rectf.xmin, &rectf.ymin);
|
||||
UI_view2d_region_to_view(v2d, rect.xmax, rect.ymax-2, &rectf.xmax, &rectf.ymax);
|
||||
|
||||
/* filter data */
|
||||
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CHANNELS);
|
||||
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
|
||||
|
||||
/* convert selection modes to selection modes */
|
||||
selectmode= selmodes_to_flagmodes(selectmode);
|
||||
|
||||
/* loop over data, doing border select */
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
ymin= ymax - NLACHANNEL_STEP;
|
||||
|
||||
/* perform vertical suitability check (if applicable) */
|
||||
if ( (mode == NLA_BORDERSEL_FRAMERANGE) ||
|
||||
!((ymax < rectf.ymin) || (ymin > rectf.ymax)) )
|
||||
{
|
||||
/* loop over data selecting (only if NLA-Track) */
|
||||
if (ale->type == ANIMTYPE_NLATRACK) {
|
||||
NlaTrack *nlt= (NlaTrack *)ale->data;
|
||||
NlaStrip *strip;
|
||||
|
||||
/* only select strips if they fall within the required ranges (if applicable) */
|
||||
for (strip= nlt->strips.first; strip; strip= strip->next) {
|
||||
if ( (mode == NLA_BORDERSEL_CHANNELS) ||
|
||||
BKE_nlastrip_within_bounds(strip, rectf.xmin, rectf.xmax) )
|
||||
{
|
||||
/* set selection */
|
||||
ACHANNEL_SET_FLAG(strip, selectmode, NLASTRIP_FLAG_SELECT);
|
||||
|
||||
/* clear active flag */
|
||||
strip->flag &= ~NLASTRIP_FLAG_ACTIVE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* set minimum extent to be the maximum of the next channel */
|
||||
ymax= ymin;
|
||||
}
|
||||
|
||||
/* cleanup */
|
||||
BLI_freelistN(&anim_data);
|
||||
}
|
||||
|
||||
/* ------------------- */
|
||||
|
||||
static int nlaedit_borderselect_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
bAnimContext ac;
|
||||
rcti rect;
|
||||
short mode=0, selectmode=0;
|
||||
int event;
|
||||
|
||||
/* get editor data */
|
||||
if (ANIM_animdata_get_context(C, &ac) == 0)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
/* get settings from operator */
|
||||
rect.xmin= RNA_int_get(op->ptr, "xmin");
|
||||
rect.ymin= RNA_int_get(op->ptr, "ymin");
|
||||
rect.xmax= RNA_int_get(op->ptr, "xmax");
|
||||
rect.ymax= RNA_int_get(op->ptr, "ymax");
|
||||
|
||||
event= RNA_int_get(op->ptr, "event_type");
|
||||
if (event == LEFTMOUSE) // FIXME... hardcoded
|
||||
selectmode = SELECT_ADD;
|
||||
else
|
||||
selectmode = SELECT_SUBTRACT;
|
||||
|
||||
/* selection 'mode' depends on whether borderselect region only matters on one axis */
|
||||
if (RNA_boolean_get(op->ptr, "axis_range")) {
|
||||
/* mode depends on which axis of the range is larger to determine which axis to use
|
||||
* - checking this in region-space is fine, as it's fundamentally still going to be a different rect size
|
||||
* - the frame-range select option is favoured over the channel one (x over y), as frame-range one is often
|
||||
* used for tweaking timing when "blocking", while channels is not that useful...
|
||||
*/
|
||||
if ((rect.xmax - rect.xmin) >= (rect.ymax - rect.ymin))
|
||||
mode= NLA_BORDERSEL_FRAMERANGE;
|
||||
else
|
||||
mode= NLA_BORDERSEL_CHANNELS;
|
||||
}
|
||||
else
|
||||
mode= NLA_BORDERSEL_ALLSTRIPS;
|
||||
|
||||
/* apply borderselect action */
|
||||
borderselect_nla_strips(&ac, rect, mode, selectmode);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_SELECT, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void NLA_OT_select_border(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Border Select";
|
||||
ot->idname= "NLA_OT_select_border";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke= WM_border_select_invoke;
|
||||
ot->exec= nlaedit_borderselect_exec;
|
||||
ot->modal= WM_border_select_modal;
|
||||
|
||||
ot->poll= nlaop_poll_tweakmode_off;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
|
||||
/* rna */
|
||||
RNA_def_int(ot->srna, "event_type", 0, INT_MIN, INT_MAX, "Event Type", "", INT_MIN, INT_MAX);
|
||||
RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX);
|
||||
RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX);
|
||||
RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX);
|
||||
RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX);
|
||||
|
||||
RNA_def_boolean(ot->srna, "axis_range", 0, "Axis Range", "");
|
||||
}
|
||||
|
||||
/* ******************** Mouse-Click Select Operator *********************** */
|
||||
/* This operator works in one of 2 ways:
|
||||
* 1) Select the strip directly under the mouse
|
||||
* 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", 0, "Check if Select Left or Right", ""},
|
||||
{NLAEDIT_LRSEL_NONE, "OFF", 0, "Don't select", ""},
|
||||
{NLAEDIT_LRSEL_LEFT, "LEFT", 0, "Before current frame", ""},
|
||||
{NLAEDIT_LRSEL_RIGHT, "RIGHT", 0, "After current frame", ""},
|
||||
{0, NULL, 0, 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 (bContext *C, bAnimContext *ac, int mval[2], short select_mode)
|
||||
{
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
bAnimListElem *ale = NULL;
|
||||
int filter;
|
||||
|
||||
View2D *v2d= &ac->ar->v2d;
|
||||
Scene *scene= ac->scene;
|
||||
NlaStrip *strip = NULL;
|
||||
int channel_index;
|
||||
float xmin, xmax, dummy;
|
||||
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, (float)NLACHANNEL_HEIGHT_HALF, x, y, NULL, &channel_index);
|
||||
|
||||
/* x-range to check is +/- 7 (in screen/region-space) on either side of mouse click
|
||||
* (that is the size of keyframe icons, so user should be expecting similar tolerances)
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/* if currently in tweakmode, exit tweakmode before changing selection states
|
||||
* now that we've found our target...
|
||||
*/
|
||||
if (scene->flag & SCE_NLA_EDIT_ON)
|
||||
WM_operator_name_call(C, "NLA_OT_tweakmode_exit", WM_OP_EXEC_DEFAULT, NULL);
|
||||
|
||||
/* for replacing selection, firstly need to clear existing selection */
|
||||
if (select_mode == SELECT_REPLACE) {
|
||||
/* reset selection mode for next steps */
|
||||
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, 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);
|
||||
|
||||
/* if we selected it, we can make it active too
|
||||
* - we always need to clear the active strip flag though...
|
||||
*/
|
||||
deselect_nla_strips(ac, DESELECT_STRIPS_CLEARACTIVE, 0);
|
||||
if (strip->flag & NLASTRIP_FLAG_SELECT)
|
||||
strip->flag |= NLASTRIP_FLAG_ACTIVE;
|
||||
}
|
||||
|
||||
/* free this channel */
|
||||
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 (bContext *C, bAnimContext *ac, short leftright, short select_mode)
|
||||
{
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
bAnimListElem *ale;
|
||||
int filter;
|
||||
|
||||
Scene *scene= ac->scene;
|
||||
float xmin, xmax;
|
||||
|
||||
/* if currently in tweakmode, exit tweakmode first */
|
||||
if (scene->flag & SCE_NLA_EDIT_ON)
|
||||
WM_operator_name_call(C, "NLA_OT_tweakmode_exit", WM_OP_EXEC_DEFAULT, NULL);
|
||||
|
||||
/* if select mode is replace, deselect all keyframes (and channels) first */
|
||||
if (select_mode==SELECT_REPLACE) {
|
||||
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 = MINAFRAMEF;
|
||||
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_NLATRACKS);
|
||||
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(C, &ac, RNA_enum_get(op->ptr, "left_right"), selectmode);
|
||||
}
|
||||
else {
|
||||
/* select strips based upon mouse position */
|
||||
mouse_nla_strips(C, &ac, mval, selectmode);
|
||||
}
|
||||
|
||||
/* set notifier that things have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_SELECT, NULL);
|
||||
|
||||
/* for tweak grab to work */
|
||||
return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH;
|
||||
}
|
||||
|
||||
void NLA_OT_click_select (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Mouse Select";
|
||||
ot->idname= "NLA_OT_click_select";
|
||||
|
||||
/* api callbacks - absolutely no exec() this yet... */
|
||||
ot->invoke= nlaedit_clickselect_invoke;
|
||||
ot->poll= ED_operator_nla_active;
|
||||
|
||||
/* 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
|
||||
}
|
||||
|
||||
/* *********************************************** */
|
||||
@@ -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,20 +64,58 @@
|
||||
#include "UI_resources.h"
|
||||
#include "UI_view2d.h"
|
||||
|
||||
#include "ED_markers.h"
|
||||
|
||||
#include "nla_intern.h" // own include
|
||||
|
||||
/* ******************** manage regions ********************* */
|
||||
|
||||
ARegion *nla_has_buttons_region(ScrArea *sa)
|
||||
{
|
||||
ARegion *ar, *arnew;
|
||||
|
||||
for (ar= sa->regionbase.first; ar; ar= ar->next) {
|
||||
if (ar->regiontype==RGN_TYPE_UI)
|
||||
return ar;
|
||||
}
|
||||
|
||||
/* add subdiv level; after main */
|
||||
for (ar= sa->regionbase.first; ar; ar= ar->next) {
|
||||
if (ar->regiontype==RGN_TYPE_WINDOW)
|
||||
break;
|
||||
}
|
||||
|
||||
/* is error! */
|
||||
if (ar==NULL) return NULL;
|
||||
|
||||
arnew= MEM_callocN(sizeof(ARegion), "buttons for nla");
|
||||
|
||||
BLI_insertlinkafter(&sa->regionbase, ar, arnew);
|
||||
arnew->regiontype= RGN_TYPE_UI;
|
||||
arnew->alignment= RGN_ALIGN_RIGHT;
|
||||
|
||||
arnew->flag = RGN_FLAG_HIDDEN;
|
||||
|
||||
return arnew;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ******************** default callbacks for nla space ***************** */
|
||||
|
||||
static SpaceLink *nla_new(const bContext *C)
|
||||
{
|
||||
Scene *scene= CTX_data_scene(C);
|
||||
ARegion *ar;
|
||||
SpaceNla *snla;
|
||||
|
||||
snla= MEM_callocN(sizeof(SpaceNla), "initnla");
|
||||
snla->spacetype= SPACE_NLA;
|
||||
|
||||
/* allocate DopeSheet data for NLA Editor */
|
||||
snla->ads= MEM_callocN(sizeof(bDopeSheet), "NlaEdit DopeSheet");
|
||||
|
||||
/* set auto-snapping settings */
|
||||
snla->autosnap = SACTSNAP_FRAME;
|
||||
|
||||
/* header */
|
||||
ar= MEM_callocN(sizeof(ARegion), "header for nla");
|
||||
|
||||
@@ -78,13 +123,23 @@ 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;
|
||||
|
||||
/* ui buttons */
|
||||
ar= MEM_callocN(sizeof(ARegion), "buttons area for nla");
|
||||
|
||||
BLI_addtail(&snla->regionbase, ar);
|
||||
ar->regiontype= RGN_TYPE_UI;
|
||||
ar->alignment= RGN_ALIGN_RIGHT;
|
||||
ar->flag = RGN_FLAG_HIDDEN;
|
||||
|
||||
/* main area */
|
||||
ar= MEM_callocN(sizeof(ARegion), "main area for nla");
|
||||
@@ -92,29 +147,26 @@ static SpaceLink *nla_new(const bContext *C)
|
||||
BLI_addtail(&snla->regionbase, ar);
|
||||
ar->regiontype= RGN_TYPE_WINDOW;
|
||||
|
||||
ar->v2d.tot.xmin= 1.0f;
|
||||
ar->v2d.tot.ymin= 0.0f;
|
||||
ar->v2d.tot.xmax= 1000.0f;
|
||||
ar->v2d.tot.ymax= 1000.0f;
|
||||
ar->v2d.tot.xmin= (float)(SFRA-10);
|
||||
ar->v2d.tot.ymin= -500.0f;
|
||||
ar->v2d.tot.xmax= (float)(EFRA+10);
|
||||
ar->v2d.tot.ymax= 0.0f;
|
||||
|
||||
ar->v2d.cur.xmin= -5.0f;
|
||||
ar->v2d.cur.ymin= 0.0f;
|
||||
ar->v2d.cur.xmax= 65.0f;
|
||||
ar->v2d.cur.ymax= 1000.0f;
|
||||
ar->v2d.cur = ar->v2d.tot;
|
||||
|
||||
ar->v2d.min[0]= 0.0f;
|
||||
ar->v2d.min[1]= 0.0f;
|
||||
ar->v2d.min[1]= 0.0f;
|
||||
|
||||
ar->v2d.max[0]= MAXFRAMEF;
|
||||
ar->v2d.max[1]= 1000.0f;
|
||||
|
||||
ar->v2d.minzoom= 0.1f;
|
||||
ar->v2d.maxzoom= 50.0f;
|
||||
|
||||
ar->v2d.scroll |= (V2D_SCROLL_BOTTOM|V2D_SCROLL_SCALE_HORIZONTAL);
|
||||
ar->v2d.max[1]= 10000.0f;
|
||||
|
||||
ar->v2d.minzoom= 0.01f;
|
||||
ar->v2d.maxzoom= 50;
|
||||
ar->v2d.scroll = (V2D_SCROLL_BOTTOM|V2D_SCROLL_SCALE_HORIZONTAL);
|
||||
ar->v2d.scroll |= (V2D_SCROLL_RIGHT);
|
||||
ar->v2d.keepzoom= V2D_LOCKZOOM_Y;
|
||||
|
||||
ar->v2d.align= V2D_ALIGN_NO_POS_Y;
|
||||
ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL;
|
||||
|
||||
return (SpaceLink *)snla;
|
||||
}
|
||||
@@ -122,15 +174,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 +200,33 @@ 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_LIST, ar->winx, ar->winy);
|
||||
|
||||
/* own keymap */
|
||||
// TODO: cannot use generic copy, need special NLA version
|
||||
keymap= WM_keymap_listbase(wm, "NLA Channels", SPACE_NLA, 0); /* XXX weak? */
|
||||
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
|
||||
keymap= WM_keymap_listbase(wm, "NLA Generic", SPACE_NLA, 0);
|
||||
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
|
||||
}
|
||||
|
||||
/* draw entirely, view changes should be handled here */
|
||||
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 +234,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 +259,22 @@ 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);
|
||||
keymap= WM_keymap_listbase(wm, "NLA Generic", SPACE_NLA, 0);
|
||||
WM_event_add_keymap_handler(&ar->handlers, keymap);
|
||||
}
|
||||
|
||||
static void nla_main_area_draw(const bContext *C, ARegion *ar)
|
||||
{
|
||||
/* 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 +282,46 @@ 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)) {
|
||||
/* strips and backdrops */
|
||||
draw_nla_main_data(&ac, snla, ar);
|
||||
|
||||
/* text draw cached, in pixelspace now */
|
||||
UI_view2d_text_cache_draw(ar);
|
||||
}
|
||||
|
||||
UI_view2d_view_ortho(C, v2d);
|
||||
|
||||
/* current frame */
|
||||
if (snla->flag & SNLA_DRAWTIME) flag |= DRAWCFRA_UNIT_SECONDS;
|
||||
if ((snla->flag & SNLA_NODRAWCFRANUM)==0) flag |= DRAWCFRA_SHOW_NUMBOX;
|
||||
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)
|
||||
@@ -239,9 +351,144 @@ static void nla_header_area_draw(const bContext *C, ARegion *ar)
|
||||
UI_view2d_view_restore(C);
|
||||
}
|
||||
|
||||
/* add handlers, stuff you only do once or on area/region changes */
|
||||
static void nla_buttons_area_init(wmWindowManager *wm, ARegion *ar)
|
||||
{
|
||||
ListBase *keymap;
|
||||
|
||||
ED_region_panels_init(wm, ar);
|
||||
|
||||
keymap= WM_keymap_listbase(wm, "NLA Generic", SPACE_NLA, 0);
|
||||
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
|
||||
}
|
||||
|
||||
static void nla_buttons_area_draw(const bContext *C, ARegion *ar)
|
||||
{
|
||||
ED_region_panels(C, ar, 1, NULL);
|
||||
}
|
||||
|
||||
static void nla_region_listener(ARegion *ar, wmNotifier *wmn)
|
||||
{
|
||||
/* context changes */
|
||||
switch(wmn->category) {
|
||||
case NC_ANIMATION:
|
||||
ED_region_tag_redraw(ar);
|
||||
break;
|
||||
case NC_SCENE:
|
||||
switch(wmn->data) {
|
||||
case ND_OB_ACTIVE:
|
||||
case ND_FRAME:
|
||||
case ND_MARKERS:
|
||||
ED_region_tag_redraw(ar);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case NC_OBJECT:
|
||||
switch(wmn->data) {
|
||||
case ND_BONE_ACTIVE:
|
||||
case ND_BONE_SELECT:
|
||||
case ND_KEYS:
|
||||
ED_region_tag_redraw(ar);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if(wmn->data==ND_KEYS)
|
||||
ED_region_tag_redraw(ar);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void nla_main_area_listener(ARegion *ar, wmNotifier *wmn)
|
||||
{
|
||||
/* context changes */
|
||||
switch(wmn->category) {
|
||||
case NC_ANIMATION:
|
||||
ED_region_tag_redraw(ar);
|
||||
break;
|
||||
case NC_SCENE:
|
||||
switch(wmn->data) {
|
||||
case ND_OB_ACTIVE:
|
||||
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_ANIMATION:
|
||||
ED_region_tag_redraw(ar);
|
||||
break;
|
||||
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_ANIMATION:
|
||||
// TODO: filter specific types of changes?
|
||||
ED_area_tag_refresh(sa);
|
||||
break;
|
||||
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 +504,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 +513,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,11 +534,25 @@ 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);
|
||||
|
||||
/* regions: UI buttons */
|
||||
art= MEM_callocN(sizeof(ARegionType), "spacetype nla region");
|
||||
art->regionid = RGN_TYPE_UI;
|
||||
art->minsizex= 200;
|
||||
art->keymapflag= ED_KEYMAP_UI;
|
||||
art->listener= nla_region_listener;
|
||||
art->init= nla_buttons_area_init;
|
||||
art->draw= nla_buttons_area_draw;
|
||||
|
||||
BLI_addhead(&st->regiontypes, art);
|
||||
|
||||
nla_buttons_register(art);
|
||||
|
||||
|
||||
BKE_spacetype_register(st);
|
||||
}
|
||||
|
||||
@@ -949,7 +949,6 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
|
||||
|
||||
/* NLA Data */
|
||||
if (adt->nla_tracks.first) {
|
||||
#if 0
|
||||
TreeElement *tenla= outliner_add_element(soops, &te->subtree, adt, te, TSE_NLA, 0);
|
||||
NlaTrack *nlt;
|
||||
int a= 0;
|
||||
@@ -957,17 +956,18 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
|
||||
tenla->name= "NLA Tracks";
|
||||
|
||||
for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
|
||||
TreeElement *tenlt= outliner_add_element(soops, &te->subtree, nlt, te, TSE_NLA_TRACK, a);
|
||||
bActionStrip *strip;
|
||||
TreeElement *tenlt= outliner_add_element(soops, &tenla->subtree, nlt, tenla, TSE_NLA_TRACK, a);
|
||||
NlaStrip *strip;
|
||||
TreeElement *ten;
|
||||
int b= 0;
|
||||
|
||||
for (strip=nlt->strips.first; strip; strip=strip->next, a++) {
|
||||
ten= outliner_add_element(soops, &tenla->subtree, strip->act, tenla, TSE_NLA_ACTION, a);
|
||||
tenlt->name= nlt->name;
|
||||
|
||||
for (strip=nlt->strips.first; strip; strip=strip->next, b++) {
|
||||
ten= outliner_add_element(soops, &tenlt->subtree, strip->act, tenlt, TSE_NLA_ACTION, b);
|
||||
if(ten) ten->directdata= strip;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else if(type==TSE_SEQUENCE) {
|
||||
@@ -3518,6 +3518,8 @@ static void tselem_draw_icon(float x, float y, TreeStoreElem *tselem, TreeElemen
|
||||
UI_icon_draw(x, y, ICON_ANIM_DATA); break; // xxx
|
||||
case TSE_NLA:
|
||||
UI_icon_draw(x, y, ICON_NLA); break;
|
||||
case TSE_NLA_TRACK:
|
||||
UI_icon_draw(x, y, ICON_NLA); break; // XXX
|
||||
case TSE_NLA_ACTION:
|
||||
UI_icon_draw(x, y, ICON_ACTION); break;
|
||||
case TSE_DEFGROUP_BASE:
|
||||
|
||||
@@ -94,6 +94,7 @@ typedef struct TreeElement {
|
||||
#define TSE_RNA_STRUCT 30
|
||||
#define TSE_RNA_PROPERTY 31
|
||||
#define TSE_RNA_ARRAY_ELEM 32
|
||||
#define TSE_NLA_TRACK 33
|
||||
|
||||
/* outliner search flags */
|
||||
#define OL_FIND 0
|
||||
|
||||
@@ -373,6 +373,7 @@ static uiBlock *time_framemenu(bContext *C, ARegion *ar, void *arg_unused)
|
||||
#define B_REDRAWALL 750
|
||||
#define B_TL_REW 751
|
||||
#define B_TL_PLAY 752
|
||||
#define B_TL_RPLAY 760
|
||||
#define B_TL_FF 753
|
||||
#define B_TL_PREVKEY 754
|
||||
#define B_TL_NEXTKEY 755
|
||||
@@ -415,6 +416,18 @@ void do_time_buttons(bContext *C, void *arg, int event)
|
||||
sad->ar= time_top_left_3dwindow(screen);
|
||||
}
|
||||
|
||||
break;
|
||||
case B_TL_RPLAY:
|
||||
ED_screen_animation_timer(C, stime->redraws, -1);
|
||||
|
||||
/* update region if TIME_REGION was set, to leftmost 3d window */
|
||||
if(screen->animtimer && (stime->redraws & TIME_REGION)) {
|
||||
wmTimer *wt= screen->animtimer;
|
||||
ScreenAnimData *sad= wt->customdata;
|
||||
|
||||
sad->ar= time_top_left_3dwindow(screen);
|
||||
}
|
||||
|
||||
break;
|
||||
case B_TL_STOP:
|
||||
ED_screen_animation_timer(C, 0, 0);
|
||||
@@ -536,9 +549,12 @@ void time_header_buttons(const bContext *C, ARegion *ar)
|
||||
|
||||
xco += (short)(4.5 * XIC + 16);
|
||||
|
||||
/* MINAFRAMEF not MINFRAMEF, since MINAFRAMEF allows to set current frame negative
|
||||
* to facilitate easier keyframing in some situations
|
||||
*/
|
||||
uiDefButI(block, NUM, B_NEWFRAME, "",
|
||||
xco,yco, (int)3.5*XIC,YIC,
|
||||
&(scene->r.cfra), MINFRAMEF, MAXFRAMEF, 0, 0,
|
||||
&(scene->r.cfra), MINAFRAMEF, MAXFRAMEF, 0, 0,
|
||||
"Displays Current Frame of animation");
|
||||
|
||||
xco += (short)(3.5 * XIC + 16);
|
||||
@@ -550,14 +566,27 @@ void time_header_buttons(const bContext *C, ARegion *ar)
|
||||
xco, yco, XIC, YIC, 0, 0, 0, 0, 0, "Skip to previous keyframe (Ctrl PageDown)");
|
||||
xco+= XIC+4;
|
||||
|
||||
if(CTX_wm_screen(C)->animtimer)
|
||||
if(CTX_wm_screen(C)->animtimer) {
|
||||
/* pause button is drawn centered between the two other buttons for now (saves drawing 2 buttons, or having position changes) */
|
||||
xco+= XIC/2 + 2;
|
||||
|
||||
uiDefIconBut(block, BUT, B_TL_STOP, ICON_PAUSE,
|
||||
xco, yco, XIC, YIC, 0, 0, 0, 0, 0, "Stop Playing Timeline");
|
||||
else
|
||||
|
||||
xco+= XIC/2 + 2;
|
||||
}
|
||||
else {
|
||||
// FIXME: the icon for this is crap
|
||||
uiDefIconBut(block, BUT, B_TL_RPLAY, ICON_REW/*ICON_PLAY*/,
|
||||
xco, yco, XIC, YIC, 0, 0, 0, 0, 0, "Play Timeline in Reverse");
|
||||
|
||||
xco+= XIC+4;
|
||||
|
||||
uiDefIconBut(block, BUT, B_TL_PLAY, ICON_PLAY,
|
||||
xco, yco, XIC, YIC, 0, 0, 0, 0, 0, "Play Timeline ");
|
||||
|
||||
}
|
||||
xco+= XIC+4;
|
||||
|
||||
uiDefIconBut(block, BUT, B_TL_NEXTKEY, ICON_NEXT_KEYFRAME,
|
||||
xco, yco, XIC, YIC, 0, 0, 0, 0, 0, "Skip to next keyframe (Ctrl PageUp)");
|
||||
xco+= XIC+4;
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "DNA_anim_types.h"
|
||||
#include "DNA_action_types.h"
|
||||
#include "DNA_armature_types.h"
|
||||
#include "DNA_constraint_types.h"
|
||||
@@ -52,6 +53,7 @@
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_arithb.h"
|
||||
|
||||
#include "BKE_animsys.h"
|
||||
#include "BKE_action.h"
|
||||
#include "BKE_armature.h"
|
||||
#include "BKE_constraint.h"
|
||||
@@ -61,6 +63,7 @@
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_modifier.h"
|
||||
#include "BKE_nla.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_utildefines.h"
|
||||
|
||||
@@ -2019,10 +2022,9 @@ static void draw_ebones(View3D *v3d, RegionView3D *rv3d, Object *ob, int dt)
|
||||
*/
|
||||
static void draw_pose_paths(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob)
|
||||
{
|
||||
AnimData *adt= BKE_animdata_from_id(&ob->id);
|
||||
bArmature *arm= ob->data;
|
||||
bPoseChannel *pchan;
|
||||
// bAction *act; // XXX old animsys - watch it!
|
||||
// bActionChannel *achan;
|
||||
ActKeyColumn *ak;
|
||||
ListBase keys;
|
||||
float *fp, *fp_start;
|
||||
@@ -2168,14 +2170,11 @@ static void draw_pose_paths(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec
|
||||
/* build list of all keyframes in active action for pchan */
|
||||
keys.first = keys.last = NULL;
|
||||
|
||||
#if 0 // XXX old animation system
|
||||
act= ob->action;
|
||||
if (act) {
|
||||
achan= get_action_channel(act, pchan->name);
|
||||
if (achan)
|
||||
ipo_to_keylist(achan->ipo, &keys, NULL, NULL);
|
||||
if (adt) {
|
||||
bActionGroup *agrp= action_groups_find_named(adt->action, pchan->name);
|
||||
if (agrp)
|
||||
agroup_to_keylist(adt, agrp, &keys, NULL);
|
||||
}
|
||||
#endif // XXX old animation system
|
||||
|
||||
/* Draw slightly-larger yellow dots at each keyframe */
|
||||
UI_ThemeColor(TH_VERTEX_SELECT);
|
||||
@@ -2254,6 +2253,7 @@ static void ghost_poses_tag_unselected(Object *ob, short unset)
|
||||
static void draw_ghost_poses_range(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base)
|
||||
{
|
||||
Object *ob= base->object;
|
||||
AnimData *adt= BKE_animdata_from_id(&ob->id);
|
||||
bArmature *arm= ob->data;
|
||||
bPose *posen, *poseo;
|
||||
float start, end, stepsize, range, colfac;
|
||||
@@ -2290,7 +2290,7 @@ static void draw_ghost_poses_range(Scene *scene, View3D *v3d, RegionView3D *rv3d
|
||||
colfac = (end - (float)CFRA) / range;
|
||||
UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128-(int)(120.0*sqrt(colfac)));
|
||||
|
||||
//do_all_pose_actions(scene, ob); // XXX old animation system
|
||||
BKE_animsys_evaluate_animdata(&ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
|
||||
where_is_pose(scene, ob);
|
||||
draw_pose_channels(scene, v3d, rv3d, base, OB_WIRE);
|
||||
}
|
||||
@@ -2315,22 +2315,22 @@ static void draw_ghost_poses_range(Scene *scene, View3D *v3d, RegionView3D *rv3d
|
||||
static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base)
|
||||
{
|
||||
Object *ob= base->object;
|
||||
bAction *act= ob->action; // XXX old animsys stuff... watch it!
|
||||
AnimData *adt= BKE_animdata_from_id(&ob->id);
|
||||
bAction *act= (adt) ? adt->action : NULL;
|
||||
bArmature *arm= ob->data;
|
||||
bPose *posen, *poseo;
|
||||
ListBase keys= {NULL, NULL};
|
||||
ActKeysInc aki = {0, 0, 0};
|
||||
ActKeyColumn *ak, *akn;
|
||||
float start, end, range, colfac, i;
|
||||
int cfrao, flago;
|
||||
|
||||
aki.start= start = (float)arm->ghostsf;
|
||||
aki.end= end = (float)arm->ghostef;
|
||||
start = (float)arm->ghostsf;
|
||||
end = (float)arm->ghostef;
|
||||
if (end <= start)
|
||||
return;
|
||||
|
||||
/* get keyframes - then clip to only within range */
|
||||
action_to_keylist(act, &keys, NULL, &aki);
|
||||
action_to_keylist(adt, act, &keys, NULL);
|
||||
range= 0;
|
||||
for (ak= keys.first; ak; ak= akn) {
|
||||
akn= ak->next;
|
||||
@@ -2366,7 +2366,7 @@ static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, RegionView3D *rv3d,
|
||||
|
||||
CFRA= (int)ak->cfra;
|
||||
|
||||
//do_all_pose_actions(scene, ob); // XXX old animation system
|
||||
BKE_animsys_evaluate_animdata(&ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
|
||||
where_is_pose(scene, ob);
|
||||
draw_pose_channels(scene, v3d, rv3d, base, OB_WIRE);
|
||||
}
|
||||
@@ -2391,38 +2391,27 @@ static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, RegionView3D *rv3d,
|
||||
static void draw_ghost_poses(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base)
|
||||
{
|
||||
Object *ob= base->object;
|
||||
AnimData *adt= BKE_animdata_from_id(&ob->id);
|
||||
bArmature *arm= ob->data;
|
||||
bPose *posen, *poseo;
|
||||
//bActionStrip *strip;
|
||||
float cur, start, end, stepsize, range, colfac, actframe, ctime;
|
||||
int cfrao, maptime, flago;
|
||||
int cfrao, flago;
|
||||
|
||||
/* pre conditions, get an action with sufficient frames */
|
||||
//if (ob->action==NULL)
|
||||
// return;
|
||||
if ELEM(NULL, adt, adt->action)
|
||||
return;
|
||||
|
||||
calc_action_range(ob->action, &start, &end, 0);
|
||||
calc_action_range(adt->action, &start, &end, 0);
|
||||
if (start == end)
|
||||
return;
|
||||
|
||||
stepsize= (float)(arm->ghostsize);
|
||||
range= (float)(arm->ghostep)*stepsize + 0.5f; /* plus half to make the for loop end correct */
|
||||
|
||||
#if 0 // XXX old animation system
|
||||
/* we only map time for armature when an active strip exists */
|
||||
for (strip=ob->nlastrips.first; strip; strip=strip->next)
|
||||
if (strip->flag & ACTSTRIP_ACTIVE)
|
||||
break;
|
||||
#endif // XXX old animsys
|
||||
|
||||
//maptime= (strip!=NULL);
|
||||
maptime= 0;
|
||||
|
||||
/* store values */
|
||||
ob->flag &= ~OB_POSEMODE;
|
||||
cfrao= CFRA;
|
||||
if (maptime) actframe= get_action_frame(ob, (float)CFRA);
|
||||
else actframe= (float)CFRA;
|
||||
actframe= BKE_nla_tweakedit_remap(adt, (float)CFRA, 0);
|
||||
flago= arm->flag;
|
||||
arm->flag &= ~(ARM_DRAWNAMES|ARM_DRAWAXES);
|
||||
|
||||
@@ -2444,11 +2433,10 @@ static void draw_ghost_poses(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base
|
||||
|
||||
/* only within action range */
|
||||
if (actframe+ctime >= start && actframe+ctime <= end) {
|
||||
if (maptime) CFRA= (int)get_action_frame_inv(ob, actframe+ctime);
|
||||
else CFRA= (int)floor(actframe+ctime);
|
||||
CFRA= (int)BKE_nla_tweakedit_remap(adt, actframe+ctime, NLATIME_CONVERT_MAP);
|
||||
|
||||
if (CFRA != cfrao) {
|
||||
//do_all_pose_actions(scene, ob); // xxx old animation system crap
|
||||
BKE_animsys_evaluate_animdata(&ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
|
||||
where_is_pose(scene, ob);
|
||||
draw_pose_channels(scene, v3d, rv3d, base, OB_WIRE);
|
||||
}
|
||||
@@ -2460,11 +2448,10 @@ static void draw_ghost_poses(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base
|
||||
|
||||
/* only within action range */
|
||||
if ((actframe-ctime >= start) && (actframe-ctime <= end)) {
|
||||
if (maptime) CFRA= (int)get_action_frame_inv(ob, actframe-ctime);
|
||||
else CFRA= (int)floor(actframe-ctime);
|
||||
CFRA= (int)BKE_nla_tweakedit_remap(adt, actframe-ctime, NLATIME_CONVERT_MAP);
|
||||
|
||||
if (CFRA != cfrao) {
|
||||
//do_all_pose_actions(scene, ob); // XXX old animation system crap...
|
||||
BKE_animsys_evaluate_animdata(&ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
|
||||
where_is_pose(scene, ob);
|
||||
draw_pose_channels(scene, v3d, rv3d, base, OB_WIRE);
|
||||
}
|
||||
|
||||
@@ -409,6 +409,15 @@ static void view3d_main_area_listener(ARegion *ar, wmNotifier *wmn)
|
||||
{
|
||||
/* context changes */
|
||||
switch(wmn->category) {
|
||||
case NC_ANIMATION:
|
||||
switch(wmn->data) {
|
||||
case ND_KEYFRAME_EDIT:
|
||||
case ND_KEYFRAME_PROP:
|
||||
case ND_NLA_ACTCHANGE:
|
||||
case ND_ANIMCHAN_SELECT:
|
||||
ED_region_tag_redraw(ar);
|
||||
break;
|
||||
}
|
||||
case NC_SCENE:
|
||||
switch(wmn->data) {
|
||||
case ND_TRANSFORM:
|
||||
|
||||
@@ -117,8 +117,7 @@
|
||||
#define TEST_EDITMESH if(obedit==0) return; \
|
||||
if( (v3d->lay & obedit->lay)==0 ) return;
|
||||
|
||||
/* XXX port over */
|
||||
static void handle_view3d_lock(void) {}
|
||||
/* XXX port over */
|
||||
static void countall(void) {}
|
||||
extern void borderselect();
|
||||
static int retopo_mesh_paint_check() {return 0;}
|
||||
@@ -201,6 +200,25 @@ static RegionView3D *wm_region_view3d(const bContext *C)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// XXX quickly ported across
|
||||
static void handle_view3d_lock(bContext *C)
|
||||
{
|
||||
Scene *scene= CTX_data_scene(C);
|
||||
ScrArea *sa= CTX_wm_area(C);
|
||||
View3D *v3d= (View3D *)CTX_wm_space_data(C);
|
||||
|
||||
if (v3d != NULL && sa != NULL) {
|
||||
if(v3d->localview==0 && v3d->scenelock && sa->spacetype==SPACE_VIEW3D) {
|
||||
|
||||
/* copy to scene */
|
||||
scene->lay= v3d->lay;
|
||||
scene->camera= v3d->camera;
|
||||
|
||||
//copy_view3d_lock(REDRAW);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX; all this context stuff... should become operator */
|
||||
void do_layer_buttons(bContext *C, short event)
|
||||
{
|
||||
@@ -230,7 +248,7 @@ void do_layer_buttons(bContext *C, short event)
|
||||
v3d->lay= (1<<20)-1;
|
||||
}
|
||||
|
||||
if(v3d->scenelock) handle_view3d_lock();
|
||||
if(v3d->scenelock) handle_view3d_lock(C);
|
||||
|
||||
/* new layers might need unflushed events events */
|
||||
DAG_scene_update_flags(scene, v3d->lay); /* tags all that moves and flushes */
|
||||
@@ -266,7 +284,7 @@ static int layers_exec(bContext *C, wmOperator *op)
|
||||
else
|
||||
v3d->lay = (1<<nr);
|
||||
|
||||
if(v3d->scenelock) handle_view3d_lock();
|
||||
if(v3d->scenelock) handle_view3d_lock(C);
|
||||
|
||||
/* new layers might need unflushed events events */
|
||||
DAG_scene_update_flags(scene, v3d->lay); /* tags all that moves and flushes */
|
||||
@@ -4303,7 +4321,7 @@ static void do_view3d_header_buttons(bContext *C, void *arg, int event)
|
||||
v3d->layact= v3d->lay;
|
||||
}
|
||||
|
||||
if(v3d->scenelock) handle_view3d_lock();
|
||||
if(v3d->scenelock) handle_view3d_lock(C);
|
||||
|
||||
ED_area_tag_redraw(sa);
|
||||
countall();
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "DNA_anim_types.h"
|
||||
#include "DNA_armature_types.h"
|
||||
#include "DNA_action_types.h" /* for some special action-editor settings */
|
||||
#include "DNA_constraint_types.h"
|
||||
@@ -76,9 +77,9 @@
|
||||
//#include "BIF_editmesh.h"
|
||||
//#include "BIF_editsima.h"
|
||||
//#include "BIF_editparticle.h"
|
||||
//#include "BIF_editaction.h"
|
||||
|
||||
#include "BKE_action.h" /* get_action_frame */
|
||||
#include "BKE_action.h"
|
||||
#include "BKE_nla.h"
|
||||
//#include "BKE_bad_level_calls.h"/* popmenu and error */
|
||||
#include "BKE_bmesh.h"
|
||||
#include "BKE_context.h"
|
||||
@@ -89,7 +90,6 @@
|
||||
#include "BKE_utildefines.h"
|
||||
#include "BKE_context.h"
|
||||
|
||||
//#include "BSE_editaction_types.h"
|
||||
//#include "BSE_view.h"
|
||||
|
||||
#include "ED_image.h"
|
||||
@@ -162,7 +162,7 @@ void convertViewVec(TransInfo *t, float *vec, short dx, short dy)
|
||||
vec[1]= aspy*(v2d->cur.ymax-v2d->cur.ymin)*(dy)/divy;
|
||||
vec[2]= 0.0f;
|
||||
}
|
||||
else if(t->spacetype==SPACE_IPO) {
|
||||
else if(ELEM(t->spacetype, SPACE_IPO, SPACE_NLA)) {
|
||||
View2D *v2d = t->view;
|
||||
float divx, divy;
|
||||
|
||||
@@ -212,7 +212,7 @@ void projectIntView(TransInfo *t, float *vec, int *adr)
|
||||
|
||||
UI_view2d_to_region_no_clip(t->view, v[0], v[1], adr, adr+1);
|
||||
}
|
||||
else if(t->spacetype==SPACE_IPO) {
|
||||
else if(ELEM(t->spacetype, SPACE_IPO, SPACE_NLA)) {
|
||||
int out[2] = {0, 0};
|
||||
|
||||
UI_view2d_view_to_region((View2D *)t->view, vec[0], vec[1], out, out+1);
|
||||
@@ -241,7 +241,7 @@ void projectFloatView(TransInfo *t, float *vec, float *adr)
|
||||
adr[0]= a[0];
|
||||
adr[1]= a[1];
|
||||
}
|
||||
else if(t->spacetype==SPACE_IPO) {
|
||||
else if(ELEM(t->spacetype, SPACE_IPO, SPACE_NLA)) {
|
||||
int a[2];
|
||||
|
||||
projectIntView(t, vec, a);
|
||||
@@ -300,24 +300,15 @@ static void viewRedrawForce(bContext *C, TransInfo *t)
|
||||
WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
|
||||
}
|
||||
else if (t->spacetype == SPACE_ACTION) {
|
||||
SpaceAction *saction= (SpaceAction *)t->sa->spacedata.first;
|
||||
|
||||
// TRANSFORM_FIX_ME
|
||||
if (saction->lock) {
|
||||
// whole window...
|
||||
}
|
||||
else
|
||||
ED_area_tag_redraw(t->sa);
|
||||
//SpaceAction *saction= (SpaceAction *)t->sa->spacedata.first;
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
|
||||
}
|
||||
else if (t->spacetype == SPACE_IPO) {
|
||||
SpaceIpo *sipo= (SpaceIpo *)t->sa->spacedata.first;
|
||||
|
||||
// TRANSFORM_FIX_ME
|
||||
if (sipo->lock) {
|
||||
// whole window...
|
||||
}
|
||||
else
|
||||
ED_area_tag_redraw(t->sa);
|
||||
//SpaceIpo *sipo= (SpaceIpo *)t->sa->spacedata.first;
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
|
||||
}
|
||||
else if (t->spacetype == SPACE_NLA) {
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
|
||||
}
|
||||
else if(t->spacetype == SPACE_NODE)
|
||||
{
|
||||
@@ -1323,10 +1314,10 @@ int initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event, int
|
||||
case TFM_TIME_EXTEND:
|
||||
/* now that transdata has been made, do like for TFM_TIME_TRANSLATE (for most Animation
|
||||
* Editors because they have only 1D transforms for time values) or TFM_TRANSLATION
|
||||
* (for Graph Editor only since it uses 'standard' transforms to get 2D movement)
|
||||
* (for Graph/NLA Editors only since they uses 'standard' transforms to get 2D movement)
|
||||
* depending on which editor this was called from
|
||||
*/
|
||||
if (t->spacetype == SPACE_IPO)
|
||||
if ELEM(t->spacetype, SPACE_IPO, SPACE_NLA)
|
||||
initTranslation(t);
|
||||
else
|
||||
initTimeTranslate(t);
|
||||
@@ -4355,7 +4346,7 @@ static short getAnimEdit_DrawTime(TransInfo *t)
|
||||
/* This function is used by Animation Editor specific transform functions to do
|
||||
* the Snap Keyframe to Nearest Frame/Marker
|
||||
*/
|
||||
static void doAnimEdit_SnapFrame(TransInfo *t, TransData *td, Object *ob, short autosnap)
|
||||
static void doAnimEdit_SnapFrame(TransInfo *t, TransData *td, AnimData *adt, short autosnap)
|
||||
{
|
||||
/* snap key to nearest frame? */
|
||||
if (autosnap == SACTSNAP_FRAME) {
|
||||
@@ -4365,8 +4356,8 @@ static void doAnimEdit_SnapFrame(TransInfo *t, TransData *td, Object *ob, short
|
||||
double val;
|
||||
|
||||
/* convert frame to nla-action time (if needed) */
|
||||
if (ob)
|
||||
val= get_action_frame_inv(ob, *(td->val));
|
||||
if (adt)
|
||||
val= BKE_nla_tweakedit_remap(adt, *(td->val), NLATIME_CONVERT_MAP);
|
||||
else
|
||||
val= *(td->val);
|
||||
|
||||
@@ -4377,8 +4368,8 @@ static void doAnimEdit_SnapFrame(TransInfo *t, TransData *td, Object *ob, short
|
||||
val= (float)( floor(val+0.5f) );
|
||||
|
||||
/* convert frame out of nla-action time */
|
||||
if (ob)
|
||||
*(td->val)= get_action_frame(ob, val);
|
||||
if (adt)
|
||||
*(td->val)= BKE_nla_tweakedit_remap(adt, val, NLATIME_CONVERT_UNMAP);
|
||||
else
|
||||
*(td->val)= val;
|
||||
}
|
||||
@@ -4387,8 +4378,8 @@ static void doAnimEdit_SnapFrame(TransInfo *t, TransData *td, Object *ob, short
|
||||
float val;
|
||||
|
||||
/* convert frame to nla-action time (if needed) */
|
||||
if (ob)
|
||||
val= get_action_frame_inv(ob, *(td->val));
|
||||
if (adt)
|
||||
val= BKE_nla_tweakedit_remap(adt, *(td->val), NLATIME_CONVERT_MAP);
|
||||
else
|
||||
val= *(td->val);
|
||||
|
||||
@@ -4397,8 +4388,8 @@ static void doAnimEdit_SnapFrame(TransInfo *t, TransData *td, Object *ob, short
|
||||
val= (float)ED_markers_find_nearest_marker_time(&t->scene->markers, val);
|
||||
|
||||
/* convert frame out of nla-action time */
|
||||
if (ob)
|
||||
*(td->val)= get_action_frame(ob, val);
|
||||
if (adt)
|
||||
*(td->val)= BKE_nla_tweakedit_remap(adt, val, NLATIME_CONVERT_UNMAP);
|
||||
else
|
||||
*(td->val)= val;
|
||||
}
|
||||
@@ -4471,13 +4462,14 @@ static void applyTimeTranslate(TransInfo *t, float sval)
|
||||
|
||||
/* it doesn't matter whether we apply to t->data or t->data2d, but t->data2d is more convenient */
|
||||
for (i = 0 ; i < t->total; i++, td++) {
|
||||
/* it is assumed that td->ob is a pointer to the object,
|
||||
/* it is assumed that td->extra is a pointer to the AnimData,
|
||||
* whose active action is where this keyframe comes from
|
||||
* (this is only valid when not in NLA)
|
||||
*/
|
||||
Object *ob= td->ob;
|
||||
AnimData *adt= (t->spacetype != SPACE_NLA) ? td->extra : NULL;
|
||||
|
||||
/* check if any need to apply nla-scaling */
|
||||
if (ob) {
|
||||
/* check if any need to apply nla-mapping */
|
||||
if (adt) {
|
||||
deltax = t->values[0];
|
||||
|
||||
if (autosnap == SACTSNAP_STEP) {
|
||||
@@ -4487,9 +4479,9 @@ static void applyTimeTranslate(TransInfo *t, float sval)
|
||||
deltax= (float)( floor(deltax + 0.5f) );
|
||||
}
|
||||
|
||||
val = get_action_frame_inv(ob, td->ival);
|
||||
val = BKE_nla_tweakedit_remap(adt, td->ival, NLATIME_CONVERT_MAP);
|
||||
val += deltax;
|
||||
*(td->val) = get_action_frame(ob, val);
|
||||
*(td->val) = BKE_nla_tweakedit_remap(adt, val, NLATIME_CONVERT_UNMAP);
|
||||
}
|
||||
else {
|
||||
deltax = val = t->values[0];
|
||||
@@ -4505,7 +4497,7 @@ static void applyTimeTranslate(TransInfo *t, float sval)
|
||||
}
|
||||
|
||||
/* apply nearest snapping */
|
||||
doAnimEdit_SnapFrame(t, td, ob, autosnap);
|
||||
doAnimEdit_SnapFrame(t, td, adt, autosnap);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4605,15 +4597,16 @@ static void applyTimeSlide(TransInfo *t, float sval)
|
||||
|
||||
/* it doesn't matter whether we apply to t->data or t->data2d, but t->data2d is more convenient */
|
||||
for (i = 0 ; i < t->total; i++, td++) {
|
||||
/* it is assumed that td->ob is a pointer to the object,
|
||||
/* it is assumed that td->extra is a pointer to the AnimData,
|
||||
* whose active action is where this keyframe comes from
|
||||
* (this is only valid when not in NLA)
|
||||
*/
|
||||
Object *ob= td->ob;
|
||||
AnimData *adt= (t->spacetype != SPACE_NLA) ? td->extra : NULL;
|
||||
float cval = t->values[0];
|
||||
|
||||
/* apply scaling to necessary values */
|
||||
if (ob)
|
||||
cval= get_action_frame(ob, cval);
|
||||
/* apply NLA-mapping to necessary values */
|
||||
if (adt)
|
||||
cval= BKE_nla_tweakedit_remap(adt, cval, NLATIME_CONVERT_UNMAP);
|
||||
|
||||
/* only apply to data if in range */
|
||||
if ((sval > minx) && (sval < maxx)) {
|
||||
@@ -4708,10 +4701,11 @@ static void applyTimeScale(TransInfo *t) {
|
||||
|
||||
|
||||
for (i = 0 ; i < t->total; i++, td++) {
|
||||
/* it is assumed that td->ob is a pointer to the object,
|
||||
/* it is assumed that td->extra is a pointer to the AnimData,
|
||||
* whose active action is where this keyframe comes from
|
||||
* (this is only valid when not in NLA)
|
||||
*/
|
||||
Object *ob= td->ob;
|
||||
AnimData *adt= (t->spacetype != SPACE_NLA) ? td->extra : NULL;
|
||||
float startx= CFRA;
|
||||
float fac= t->values[0];
|
||||
|
||||
@@ -4722,9 +4716,9 @@ static void applyTimeScale(TransInfo *t) {
|
||||
fac= (float)( floor(fac + 0.5f) );
|
||||
}
|
||||
|
||||
/* check if any need to apply nla-scaling */
|
||||
if (ob)
|
||||
startx= get_action_frame(ob, startx);
|
||||
/* check if any need to apply nla-mapping */
|
||||
if (adt)
|
||||
startx= BKE_nla_tweakedit_remap(adt, startx, NLATIME_CONVERT_UNMAP);
|
||||
|
||||
/* now, calculate the new value */
|
||||
*(td->val) = td->ival - startx;
|
||||
@@ -4732,7 +4726,7 @@ static void applyTimeScale(TransInfo *t) {
|
||||
*(td->val) += startx;
|
||||
|
||||
/* apply nearest snapping */
|
||||
doAnimEdit_SnapFrame(t, td, ob, autosnap);
|
||||
doAnimEdit_SnapFrame(t, td, adt, autosnap);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4746,18 +4740,6 @@ int TimeScale(TransInfo *t, short mval[2])
|
||||
sval= t->imval[0];
|
||||
cval= mval[0];
|
||||
|
||||
// XXX ewww... we need a better factor!
|
||||
#if 0 // TRANSFORM_FIX_ME
|
||||
switch (t->spacetype) {
|
||||
case SPACE_ACTION:
|
||||
width= ACTWIDTH;
|
||||
break;
|
||||
case SPACE_NLA:
|
||||
width= NLAWIDTH;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* calculate scaling factor */
|
||||
startx= sval-(width/2+(t->ar->winx)/2);
|
||||
deltax= cval-(width/2+(t->ar->winx)/2);
|
||||
|
||||
@@ -161,6 +161,21 @@ typedef struct TransDataSeq {
|
||||
|
||||
} TransDataSeq;
|
||||
|
||||
/* for NLA transform (stored in td->extra pointer) */
|
||||
typedef struct TransDataNla {
|
||||
struct NlaTrack *oldTrack; /* Original NLA-Track that the strip belongs to */
|
||||
struct NlaTrack *nlt; /* Current NLA-Track that the strip belongs to */
|
||||
|
||||
struct NlaStrip *strip; /* NLA-strip this data represents */
|
||||
|
||||
/* dummy values for transform to write in - must have 3 elements... */
|
||||
float h1[3]; /* start handle */
|
||||
float h2[3]; /* end handle */
|
||||
|
||||
int trackIndex; /* index of track that strip is currently in */
|
||||
int handle; /* handle-index: 0 for dummy entry, -1 for start, 1 for end, 2 for both ends */
|
||||
} TransDataNla;
|
||||
|
||||
typedef struct TransData {
|
||||
float dist; /* Distance needed to affect element (for Proportionnal Editing) */
|
||||
float rdist; /* Distance to the nearest element (for Proportionnal Editing) */
|
||||
|
||||
@@ -90,6 +90,7 @@
|
||||
#include "BKE_mball.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_modifier.h"
|
||||
#include "BKE_nla.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_particle.h"
|
||||
#include "BKE_sequence.h"
|
||||
@@ -100,16 +101,13 @@
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_report.h"
|
||||
|
||||
//#include "BIF_editaction.h"
|
||||
//#include "BIF_editview.h"
|
||||
//#include "BIF_editlattice.h"
|
||||
//#include "BIF_editconstraint.h"
|
||||
//#include "BIF_editmesh.h"
|
||||
//#include "BIF_editnla.h"
|
||||
//#include "BIF_editsima.h"
|
||||
//#include "BIF_editparticle.h"
|
||||
#include "BIF_gl.h"
|
||||
//#include "BIF_keyframing.h"
|
||||
//#include "BIF_poseobject.h"
|
||||
//#include "BIF_meshtools.h"
|
||||
//#include "BIF_mywindow.h"
|
||||
@@ -125,6 +123,7 @@
|
||||
#include "ED_keyframing.h"
|
||||
#include "ED_keyframes_edit.h"
|
||||
#include "ED_object.h"
|
||||
#include "ED_markers.h"
|
||||
#include "ED_mesh.h"
|
||||
#include "ED_retopo.h"
|
||||
#include "ED_types.h"
|
||||
@@ -133,13 +132,7 @@
|
||||
|
||||
#include "UI_view2d.h"
|
||||
|
||||
//#include "BSE_drawipo.h"
|
||||
//#include "BSE_edit.h"
|
||||
//#include "BSE_editipo.h"
|
||||
//#include "BSE_editipo_types.h"
|
||||
//#include "BSE_editaction_types.h"
|
||||
|
||||
//#include "BDR_drawaction.h" // list of keyframes in action
|
||||
//#include "BDR_editobject.h" // reset_slowparents()
|
||||
//#include "BDR_gpencil.h"
|
||||
|
||||
@@ -2559,7 +2552,216 @@ int clipUVTransform(TransInfo *t, float *vec, int resize)
|
||||
return (clipx || clipy);
|
||||
}
|
||||
|
||||
/* ********************* ACTION/NLA EDITOR ****************** */
|
||||
/* ********************* ANIMATION EDITORS (GENERAL) ************************* */
|
||||
|
||||
/* This function tests if a point is on the "mouse" side of the cursor/frame-marking */
|
||||
static short FrameOnMouseSide(char side, float frame, float cframe)
|
||||
{
|
||||
/* both sides, so it doesn't matter */
|
||||
if (side == 'B') return 1;
|
||||
|
||||
/* only on the named side */
|
||||
if (side == 'R')
|
||||
return (frame >= cframe) ? 1 : 0;
|
||||
else
|
||||
return (frame <= cframe) ? 1 : 0;
|
||||
}
|
||||
|
||||
/* ********************* NLA EDITOR ************************* */
|
||||
|
||||
static void createTransNlaData(bContext *C, TransInfo *t)
|
||||
{
|
||||
Scene *scene= CTX_data_scene(C);
|
||||
TransData *td = NULL;
|
||||
TransDataNla *tdn = NULL;
|
||||
|
||||
bAnimContext ac;
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
bAnimListElem *ale;
|
||||
int filter;
|
||||
|
||||
int count=0;
|
||||
char side;
|
||||
|
||||
/* determine what type of data we are operating on */
|
||||
if (ANIM_animdata_get_context(C, &ac) == 0)
|
||||
return;
|
||||
|
||||
/* filter data */
|
||||
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT);
|
||||
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
|
||||
|
||||
/* which side of the current frame should be allowed */
|
||||
if (t->mode == TFM_TIME_EXTEND) {
|
||||
/* only side on which mouse is gets transformed */
|
||||
float xmouse, ymouse;
|
||||
|
||||
UI_view2d_region_to_view(&ac.ar->v2d, t->imval[0], t->imval[1], &xmouse, &ymouse);
|
||||
side = (xmouse > CFRA) ? 'R' : 'L'; // XXX use t->frame_side
|
||||
}
|
||||
else {
|
||||
/* normal transform - both sides of current frame are considered */
|
||||
side = 'B';
|
||||
}
|
||||
|
||||
/* loop 1: count how many strips are selected (consider each strip as 2 points) */
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
NlaTrack *nlt= (NlaTrack *)ale->data;
|
||||
NlaStrip *strip;
|
||||
|
||||
/* make some meta-strips for chains of selected strips */
|
||||
BKE_nlastrips_make_metas(&nlt->strips, 1);
|
||||
|
||||
/* only consider selected strips */
|
||||
for (strip= nlt->strips.first; strip; strip= strip->next) {
|
||||
// TODO: we can make strips have handles later on...
|
||||
/* transition strips can't get directly transformed */
|
||||
if (strip->type != NLASTRIP_TYPE_TRANSITION) {
|
||||
if (strip->flag & NLASTRIP_FLAG_SELECT) {
|
||||
if (FrameOnMouseSide(side, strip->start, (float)CFRA)) count++;
|
||||
if (FrameOnMouseSide(side, strip->end, (float)CFRA)) count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* stop if trying to build list if nothing selected */
|
||||
if (count == 0) {
|
||||
/* cleanup temp list */
|
||||
BLI_freelistN(&anim_data);
|
||||
return;
|
||||
}
|
||||
|
||||
/* allocate memory for data */
|
||||
t->total= count;
|
||||
|
||||
t->data= MEM_callocN(t->total*sizeof(TransData), "TransData(NLA Editor)");
|
||||
td= t->data;
|
||||
t->customData= MEM_callocN(t->total*sizeof(TransDataNla), "TransDataNla (NLA Editor)");
|
||||
tdn= t->customData;
|
||||
|
||||
/* loop 2: build transdata array */
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
/* only if a real NLA-track */
|
||||
if (ale->type == ANIMTYPE_NLATRACK) {
|
||||
NlaTrack *nlt= (NlaTrack *)ale->data;
|
||||
NlaStrip *strip;
|
||||
|
||||
/* only consider selected strips */
|
||||
for (strip= nlt->strips.first; strip; strip= strip->next) {
|
||||
// TODO: we can make strips have handles later on...
|
||||
/* transition strips can't get directly transformed */
|
||||
if (strip->type != NLASTRIP_TYPE_TRANSITION) {
|
||||
if (strip->flag & NLASTRIP_FLAG_SELECT) {
|
||||
/* our transform data is constructed as follows:
|
||||
* - only the handles on the right side of the current-frame get included
|
||||
* - td structs are transform-elements operated on by the transform system
|
||||
* and represent a single handle. The storage/pointer used (val or loc) depends on
|
||||
* whether we're scaling or transforming. Ultimately though, the handles
|
||||
* the td writes to will simply be a dummy in tdn
|
||||
* - for each strip being transformed, a single tdn struct is used, so in some
|
||||
* cases, there will need to be 1 of these tdn elements in the array skipped...
|
||||
*/
|
||||
float center[3], yval;
|
||||
|
||||
/* firstly, init tdn settings */
|
||||
tdn->oldTrack= tdn->nlt= nlt;
|
||||
tdn->strip= strip;
|
||||
tdn->trackIndex= BLI_findindex(&nlt->strips, strip);
|
||||
|
||||
yval= (float)(tdn->trackIndex * NLACHANNEL_STEP);
|
||||
|
||||
tdn->h1[0]= strip->start;
|
||||
tdn->h1[1]= yval;
|
||||
tdn->h2[0]= strip->end;
|
||||
tdn->h2[1]= yval;
|
||||
|
||||
center[0]= (float)CFRA;
|
||||
center[1]= yval;
|
||||
center[2]= 0.0f;
|
||||
|
||||
/* set td's based on which handles are applicable */
|
||||
if (FrameOnMouseSide(side, strip->start, (float)CFRA))
|
||||
{
|
||||
/* just set tdn to assume that it only has one handle for now */
|
||||
tdn->handle= -1;
|
||||
|
||||
/* now, link the transform data up to this data */
|
||||
if (t->mode == TFM_TRANSLATION) {
|
||||
td->loc= tdn->h1;
|
||||
VECCOPY(td->iloc, tdn->h1);
|
||||
|
||||
/* store all the other gunk that is required by transform */
|
||||
VECCOPY(td->center, center);
|
||||
memset(td->axismtx, 0, sizeof(td->axismtx));
|
||||
td->axismtx[2][2] = 1.0f;
|
||||
|
||||
td->ext= NULL; td->tdi= NULL; td->val= NULL;
|
||||
|
||||
td->flag |= TD_SELECTED;
|
||||
td->dist= 0.0f;
|
||||
|
||||
Mat3One(td->mtx);
|
||||
Mat3One(td->smtx);
|
||||
}
|
||||
else {
|
||||
td->val= &tdn->h1[0];
|
||||
td->ival= tdn->h1[0];
|
||||
}
|
||||
|
||||
td->extra= tdn;
|
||||
td++;
|
||||
}
|
||||
if (FrameOnMouseSide(side, strip->end, (float)CFRA))
|
||||
{
|
||||
/* if tdn is already holding the start handle, then we're doing both, otherwise, only end */
|
||||
tdn->handle= (tdn->handle) ? 2 : 1;
|
||||
|
||||
/* now, link the transform data up to this data */
|
||||
if (t->mode == TFM_TRANSLATION) {
|
||||
td->loc= tdn->h2;
|
||||
VECCOPY(td->iloc, tdn->h2);
|
||||
|
||||
/* store all the other gunk that is required by transform */
|
||||
VECCOPY(td->center, center);
|
||||
memset(td->axismtx, 0, sizeof(td->axismtx));
|
||||
td->axismtx[2][2] = 1.0f;
|
||||
|
||||
td->ext= NULL; td->tdi= NULL; td->val= NULL;
|
||||
|
||||
td->flag |= TD_SELECTED;
|
||||
td->dist= 0.0f;
|
||||
|
||||
Mat3One(td->mtx);
|
||||
Mat3One(td->smtx);
|
||||
}
|
||||
else {
|
||||
td->val= &tdn->h2[0];
|
||||
td->ival= tdn->h2[0];
|
||||
}
|
||||
|
||||
td->extra= tdn;
|
||||
td++;
|
||||
}
|
||||
|
||||
/* if both handles were used, skip the next tdn (i.e. leave it blank) since the counting code is dumb...
|
||||
* otherwise, just advance to the next one...
|
||||
*/
|
||||
if (tdn->handle == 2)
|
||||
tdn += 2;
|
||||
else
|
||||
tdn++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* cleanup temp list */
|
||||
BLI_freelistN(&anim_data);
|
||||
}
|
||||
|
||||
/* ********************* ACTION EDITOR ****************** */
|
||||
|
||||
/* Called by special_aftertrans_update to make sure selected gp-frames replace
|
||||
* any other gp-frames which may reside on that frame (that are not selected).
|
||||
@@ -2730,12 +2932,12 @@ static void posttrans_action_clean (bAnimContext *ac, bAction *act)
|
||||
* - all keyframes are converted in/out of global time
|
||||
*/
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
Object *nob= ANIM_nla_mapping_get(ac, ale);
|
||||
AnimData *adt= ANIM_nla_mapping_get(ac, ale);
|
||||
|
||||
if (nob) {
|
||||
//ANIM_nla_mapping_apply_ipocurve(nob, ale->key_data, 0, 1);
|
||||
if (adt) {
|
||||
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
|
||||
posttrans_fcurve_clean(ale->key_data);
|
||||
//ANIM_nla_mapping_apply_ipocurve(nob, ale->key_data, 1, 1);
|
||||
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
|
||||
}
|
||||
else
|
||||
posttrans_fcurve_clean(ale->key_data);
|
||||
@@ -2747,19 +2949,6 @@ static void posttrans_action_clean (bAnimContext *ac, bAction *act)
|
||||
|
||||
/* ----------------------------- */
|
||||
|
||||
/* This function tests if a point is on the "mouse" side of the cursor/frame-marking */
|
||||
static short FrameOnMouseSide(char side, float frame, float cframe)
|
||||
{
|
||||
/* both sides, so it doesn't matter */
|
||||
if (side == 'B') return 1;
|
||||
|
||||
/* only on the named side */
|
||||
if (side == 'R')
|
||||
return (frame >= cframe) ? 1 : 0;
|
||||
else
|
||||
return (frame <= cframe) ? 1 : 0;
|
||||
}
|
||||
|
||||
/* fully select selected beztriples, but only include if it's on the right side of cfra */
|
||||
static int count_fcurve_keys(FCurve *fcu, char side, float cfra)
|
||||
{
|
||||
@@ -2808,17 +2997,16 @@ static int count_gplayer_frames(bGPDlayer *gpl, char side, float cfra)
|
||||
#endif
|
||||
|
||||
/* This function assigns the information to transdata */
|
||||
static void TimeToTransData(TransData *td, float *time, Object *ob)
|
||||
static void TimeToTransData(TransData *td, float *time, AnimData *adt)
|
||||
{
|
||||
/* memory is calloc'ed, so that should zero everything nicely for us */
|
||||
td->val = time;
|
||||
td->ival = *(time);
|
||||
|
||||
/* store the Object where this keyframe exists as a keyframe of the
|
||||
* active action as td->ob. Usually, this member is only used for constraints
|
||||
* drawing
|
||||
/* store the AnimData where this keyframe exists as a keyframe of the
|
||||
* active action as td->extra.
|
||||
*/
|
||||
td->ob= ob;
|
||||
td->extra= adt;
|
||||
}
|
||||
|
||||
/* This function advances the address to which td points to, so it must return
|
||||
@@ -2828,7 +3016,7 @@ static void TimeToTransData(TransData *td, float *time, Object *ob)
|
||||
* The 'side' argument is needed for the extend mode. 'B' = both sides, 'R'/'L' mean only data
|
||||
* on the named side are used.
|
||||
*/
|
||||
static TransData *FCurveToTransData(TransData *td, FCurve *fcu, Object *ob, char side, float cfra)
|
||||
static TransData *FCurveToTransData(TransData *td, FCurve *fcu, AnimData *adt, char side, float cfra)
|
||||
{
|
||||
BezTriple *bezt;
|
||||
int i;
|
||||
@@ -2842,13 +3030,13 @@ static TransData *FCurveToTransData(TransData *td, FCurve *fcu, Object *ob, char
|
||||
/* only add if on the right 'side' of the current frame */
|
||||
if (FrameOnMouseSide(side, bezt->vec[1][0], cfra)) {
|
||||
/* each control point needs to be added separetely */
|
||||
TimeToTransData(td, bezt->vec[0], ob);
|
||||
TimeToTransData(td, bezt->vec[0], adt);
|
||||
td++;
|
||||
|
||||
TimeToTransData(td, bezt->vec[1], ob);
|
||||
TimeToTransData(td, bezt->vec[1], adt);
|
||||
td++;
|
||||
|
||||
TimeToTransData(td, bezt->vec[2], ob);
|
||||
TimeToTransData(td, bezt->vec[2], adt);
|
||||
td++;
|
||||
}
|
||||
}
|
||||
@@ -2958,13 +3146,13 @@ static void createTransActionData(bContext *C, TransInfo *t)
|
||||
|
||||
/* loop 1: fully select ipo-keys and count how many BezTriples are selected */
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
Object *nob= ANIM_nla_mapping_get(&ac, ale);
|
||||
AnimData *adt= ANIM_nla_mapping_get(&ac, ale);
|
||||
|
||||
/* convert current-frame to action-time (slightly less accurate, espcially under
|
||||
* higher scaling ratios, but is faster than converting all points)
|
||||
*/
|
||||
if (nob)
|
||||
cfra = get_action_frame(nob, (float)CFRA);
|
||||
if (adt)
|
||||
cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
|
||||
else
|
||||
cfra = (float)CFRA;
|
||||
|
||||
@@ -3011,18 +3199,18 @@ static void createTransActionData(bContext *C, TransInfo *t)
|
||||
// tfd += i;
|
||||
//}
|
||||
//else {
|
||||
Object *nob= ANIM_nla_mapping_get(&ac, ale);
|
||||
AnimData *adt= ANIM_nla_mapping_get(&ac, ale);
|
||||
FCurve *fcu= (FCurve *)ale->key_data;
|
||||
|
||||
/* convert current-frame to action-time (slightly less accurate, espcially under
|
||||
* higher scaling ratios, but is faster than converting all points)
|
||||
*/
|
||||
if (nob)
|
||||
cfra = get_action_frame(nob, (float)CFRA);
|
||||
if (adt)
|
||||
cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
|
||||
else
|
||||
cfra = (float)CFRA;
|
||||
|
||||
td= FCurveToTransData(td, fcu, nob, side, cfra);
|
||||
td= FCurveToTransData(td, fcu, adt, side, cfra);
|
||||
//}
|
||||
}
|
||||
|
||||
@@ -3051,28 +3239,26 @@ static void createTransActionData(bContext *C, TransInfo *t)
|
||||
|
||||
/* ********************* GRAPH EDITOR ************************* */
|
||||
|
||||
|
||||
|
||||
/* Helper function for createTransGraphEditData, which is reponsible for associating
|
||||
* source data with transform data
|
||||
*/
|
||||
static void bezt_to_transdata (TransData *td, TransData2D *td2d, Object *nob, float *loc, float *cent, short selected, short ishandle, short intvals)
|
||||
static void bezt_to_transdata (TransData *td, TransData2D *td2d, AnimData *adt, float *loc, float *cent, short selected, short ishandle, short intvals)
|
||||
{
|
||||
/* New location from td gets dumped onto the old-location of td2d, which then
|
||||
* gets copied to the actual data at td2d->loc2d (bezt->vec[n])
|
||||
*
|
||||
* Due to NLA scaling, we apply NLA scaling to some of the verts here,
|
||||
* and then that scaling will be undone after transform is done.
|
||||
* Due to NLA mapping, we apply NLA mapping to some of the verts here,
|
||||
* and then that mapping will be undone after transform is done.
|
||||
*/
|
||||
|
||||
if (nob) {
|
||||
td2d->loc[0] = get_action_frame_inv(nob, loc[0]);
|
||||
if (adt) {
|
||||
td2d->loc[0] = BKE_nla_tweakedit_remap(adt, loc[0], NLATIME_CONVERT_UNMAP);
|
||||
td2d->loc[1] = loc[1];
|
||||
td2d->loc[2] = 0.0f;
|
||||
td2d->loc2d = loc;
|
||||
|
||||
td->loc = td2d->loc;
|
||||
td->center[0] = get_action_frame_inv(nob, cent[0]);
|
||||
td->center[0] = BKE_nla_tweakedit_remap(adt, cent[0], NLATIME_CONVERT_UNMAP);
|
||||
td->center[1] = cent[1];
|
||||
td->center[2] = 0.0f;
|
||||
|
||||
@@ -3093,6 +3279,9 @@ static void bezt_to_transdata (TransData *td, TransData2D *td2d, Object *nob, fl
|
||||
td->axismtx[2][2] = 1.0f;
|
||||
|
||||
td->ext= NULL; td->tdi= NULL; td->val= NULL;
|
||||
|
||||
/* store AnimData info in td->extra, for applying mapping when flushing */
|
||||
td->extra= adt;
|
||||
|
||||
if (selected) {
|
||||
td->flag |= TD_SELECTED;
|
||||
@@ -3153,14 +3342,14 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
|
||||
|
||||
/* loop 1: count how many BezTriples (specifically their verts) are selected (or should be edited) */
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
Object *nob= NULL; //ANIM_nla_mapping_get(&ac, ale); // XXX we don't handle NLA mapping for now here...
|
||||
AnimData *adt= ANIM_nla_mapping_get(&ac, ale);
|
||||
FCurve *fcu= (FCurve *)ale->key_data;
|
||||
|
||||
/* convert current-frame to action-time (slightly less accurate, espcially under
|
||||
* higher scaling ratios, but is faster than converting all points)
|
||||
*/
|
||||
if (nob)
|
||||
cfra = get_action_frame(nob, (float)CFRA);
|
||||
if (adt)
|
||||
cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
|
||||
else
|
||||
cfra = (float)CFRA;
|
||||
|
||||
@@ -3210,13 +3399,19 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
|
||||
td2d= t->data2d;
|
||||
|
||||
/* loop 2: build transdata arrays */
|
||||
cfra = (float)CFRA;
|
||||
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
Object *nob= NULL; //ANIM_nla_mapping_get(&ac, ale); // XXX we don't handle NLA mapping here yet
|
||||
AnimData *adt= ANIM_nla_mapping_get(&ac, ale);
|
||||
FCurve *fcu= (FCurve *)ale->key_data;
|
||||
short intvals= (fcu->flag & FCURVE_INT_VALUES);
|
||||
|
||||
/* convert current-frame to action-time (slightly less accurate, espcially under
|
||||
* higher scaling ratios, but is faster than converting all points)
|
||||
*/
|
||||
if (adt)
|
||||
cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
|
||||
else
|
||||
cfra = (float)CFRA;
|
||||
|
||||
/* only include BezTriples whose 'keyframe' occurs on the same side of the current frame as mouse (if applicable) */
|
||||
bezt= fcu->bezt;
|
||||
prevbezt= NULL;
|
||||
@@ -3230,7 +3425,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
|
||||
if ( (!prevbezt && (bezt->ipo==BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo==BEZT_IPO_BEZ)) ) {
|
||||
if (bezt->f1 & SELECT) {
|
||||
hdata = initTransDataCurveHandes(td, bezt);
|
||||
bezt_to_transdata(td++, td2d++, nob, bezt->vec[0], bezt->vec[1], 1, 1, intvals);
|
||||
bezt_to_transdata(td++, td2d++, adt, bezt->vec[0], bezt->vec[1], 1, 1, intvals);
|
||||
}
|
||||
else
|
||||
h1= 0;
|
||||
@@ -3239,7 +3434,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
|
||||
if (bezt->f3 & SELECT) {
|
||||
if (hdata==NULL)
|
||||
hdata = initTransDataCurveHandes(td, bezt);
|
||||
bezt_to_transdata(td++, td2d++, nob, bezt->vec[2], bezt->vec[1], 1, 1, intvals);
|
||||
bezt_to_transdata(td++, td2d++, adt, bezt->vec[2], bezt->vec[1], 1, 1, intvals);
|
||||
}
|
||||
else
|
||||
h2= 0;
|
||||
@@ -3255,7 +3450,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
|
||||
hdata = initTransDataCurveHandes(td, bezt);
|
||||
}
|
||||
|
||||
bezt_to_transdata(td++, td2d++, nob, bezt->vec[1], bezt->vec[1], 1, 0, intvals);
|
||||
bezt_to_transdata(td++, td2d++, adt, bezt->vec[1], bezt->vec[1], 1, 0, intvals);
|
||||
}
|
||||
|
||||
/* special hack (must be done after initTransDataCurveHandes(), as that stores handle settings to restore...):
|
||||
@@ -3475,30 +3670,37 @@ void flushTransGraphData(TransInfo *t)
|
||||
SpaceIpo *sipo = (SpaceIpo *)t->sa->spacedata.first;
|
||||
TransData *td;
|
||||
TransData2D *td2d;
|
||||
Scene *scene= t->scene;
|
||||
double secf= FPS;
|
||||
int a;
|
||||
|
||||
/* flush to 2d vector from internally used 3d vector */
|
||||
for (a=0, td= t->data, td2d=t->data2d; a<t->total; a++, td++, td2d++) {
|
||||
AnimData *adt= (AnimData *)td->extra; /* pointers to relevant AnimData blocks are stored in the td->extra pointers */
|
||||
|
||||
/* handle snapping for time values
|
||||
* - we should still be in NLA-mapping timespace
|
||||
* - only apply to keyframes (but never to handles)
|
||||
*/
|
||||
if ((td->flag & TD_NOTIMESNAP)==0) {
|
||||
switch (sipo->autosnap) {
|
||||
case SACTSNAP_FRAME: /* snap to nearest frame */
|
||||
td2d->loc[0]= (float)( floor(td2d->loc[0]+0.5f) );
|
||||
case SACTSNAP_FRAME: /* snap to nearest frame (or second if drawing seconds) */
|
||||
if (sipo->flag & SIPO_DRAWTIME)
|
||||
td2d->loc[0]= (float)( floor((td2d->loc[0]/secf) + 0.5f) * secf );
|
||||
else
|
||||
td2d->loc[0]= (float)( floor(td2d->loc[0]+0.5f) );
|
||||
break;
|
||||
|
||||
case SACTSNAP_MARKER: /* snap to nearest marker */
|
||||
//td2d->loc[0]= (float)find_nearest_marker_time(td2d->loc[0]);
|
||||
td2d->loc[0]= (float)ED_markers_find_nearest_marker_time(&t->scene->markers, td2d->loc[0]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* we need to unapply the nla-scaling from the time in some situations */
|
||||
//if (NLA_IPO_SCALED)
|
||||
// td2d->loc2d[0]= get_action_frame(OBACT, td2d->loc[0]);
|
||||
//else
|
||||
if (adt)
|
||||
td2d->loc2d[0]= BKE_nla_tweakedit_remap(adt, td2d->loc[0], NLATIME_CONVERT_UNMAP);
|
||||
else
|
||||
td2d->loc2d[0]= td2d->loc[0];
|
||||
|
||||
/* if int-values only, truncate to integers */
|
||||
@@ -3509,7 +3711,6 @@ void flushTransGraphData(TransInfo *t)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* **************** IpoKey stuff, for Object TransData ********** */
|
||||
|
||||
/* while transforming */
|
||||
@@ -4477,16 +4678,16 @@ void special_aftertrans_update(TransInfo *t)
|
||||
|
||||
/* these should all be ipo-blocks */
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
Object *nob= ANIM_nla_mapping_get(&ac, ale);
|
||||
AnimData *adt= ANIM_nla_mapping_get(&ac, ale);
|
||||
FCurve *fcu= (FCurve *)ale->key_data;
|
||||
|
||||
if ( (saction->flag & SACTION_NOTRANSKEYCULL)==0 &&
|
||||
((cancelled == 0) || (duplicate)) )
|
||||
{
|
||||
if (nob) {
|
||||
ANIM_nla_mapping_apply_fcurve(nob, fcu, 0, 1);
|
||||
if (adt) {
|
||||
ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 1);
|
||||
posttrans_fcurve_clean(fcu);
|
||||
ANIM_nla_mapping_apply_fcurve(nob, fcu, 1, 1);
|
||||
ANIM_nla_mapping_apply_fcurve(adt, fcu, 1, 1);
|
||||
}
|
||||
else
|
||||
posttrans_fcurve_clean(fcu);
|
||||
@@ -4588,16 +4789,16 @@ void special_aftertrans_update(TransInfo *t)
|
||||
|
||||
/* these should all be ipo-blocks */
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
Object *nob= ANIM_nla_mapping_get(&ac, ale);
|
||||
AnimData *adt= ANIM_nla_mapping_get(&ac, ale);
|
||||
FCurve *fcu= (FCurve *)ale->key_data;
|
||||
|
||||
if ( (sipo->flag & SIPO_NOTRANSKEYCULL)==0 &&
|
||||
((cancelled == 0) || (duplicate)) )
|
||||
{
|
||||
if (nob) {
|
||||
ANIM_nla_mapping_apply_fcurve(nob, fcu, 0, 1);
|
||||
if (adt) {
|
||||
ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 1);
|
||||
posttrans_fcurve_clean(fcu);
|
||||
ANIM_nla_mapping_apply_fcurve(nob, fcu, 1, 1);
|
||||
ANIM_nla_mapping_apply_fcurve(adt, fcu, 1, 1);
|
||||
}
|
||||
else
|
||||
posttrans_fcurve_clean(fcu);
|
||||
@@ -4611,6 +4812,51 @@ void special_aftertrans_update(TransInfo *t)
|
||||
/* make sure all F-Curves are set correctly */
|
||||
ANIM_editkeyframes_refresh(&ac);
|
||||
}
|
||||
else if (t->spacetype == SPACE_NLA) {
|
||||
Scene *scene;
|
||||
bAnimContext ac;
|
||||
|
||||
/* initialise relevant anim-context 'context' data from TransInfo data */
|
||||
/* NOTE: sync this with the code in ANIM_animdata_get_context() */
|
||||
memset(&ac, 0, sizeof(bAnimContext));
|
||||
|
||||
scene= ac.scene= t->scene;
|
||||
ob= ac.obact= OBACT;
|
||||
ac.sa= t->sa;
|
||||
ac.ar= t->ar;
|
||||
ac.spacetype= (t->sa)? t->sa->spacetype : 0;
|
||||
ac.regiontype= (t->ar)? t->ar->regiontype : 0;
|
||||
|
||||
if (ANIM_animdata_context_getdata(&ac) == 0)
|
||||
return;
|
||||
|
||||
if (ac.datatype)
|
||||
{
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
bAnimListElem *ale;
|
||||
short filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NLATRACKS);
|
||||
|
||||
/* get channels to work on */
|
||||
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
|
||||
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
NlaTrack *nlt= (NlaTrack *)ale->data;
|
||||
|
||||
/* make sure strips are in order again */
|
||||
BKE_nlatrack_sort_strips(nlt);
|
||||
|
||||
/* remove the temp metas */
|
||||
BKE_nlastrips_clear_metas(&nlt->strips, 0, 1);
|
||||
}
|
||||
|
||||
/* free temp memory */
|
||||
BLI_freelistN(&anim_data);
|
||||
}
|
||||
|
||||
// XXX check on the calls below... we need some of these sanity checks
|
||||
//synchronize_action_strips();
|
||||
//ANIM_editkeyframes_refresh(&ac);
|
||||
}
|
||||
else if (t->obedit) {
|
||||
// TRANSFORM_FIX_ME
|
||||
// if (t->mode==TFM_BONESIZE || t->mode==TFM_BONE_ENVELOPE)
|
||||
@@ -4695,24 +4941,6 @@ void special_aftertrans_update(TransInfo *t)
|
||||
}
|
||||
}
|
||||
|
||||
#if 0 // TRANSFORM_FIX_ME
|
||||
else if (t->spacetype == SPACE_NLA) {
|
||||
recalc_all_ipos(); // bad
|
||||
synchronize_action_strips();
|
||||
|
||||
/* cleanup */
|
||||
for (base=t->scene->base.first; base; base=base->next)
|
||||
base->flag &= ~(BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA);
|
||||
|
||||
/* after transform, remove duplicate keyframes on a frame that resulted from transform */
|
||||
if ( (G.snla->flag & SNLA_NOTRANSKEYCULL)==0 &&
|
||||
((cancelled == 0) || (duplicate)) )
|
||||
{
|
||||
posttrans_nla_clean(t);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
clear_trans_object_base_flags(t);
|
||||
|
||||
#if 0 // TRANSFORM_FIX_ME
|
||||
@@ -4945,8 +5173,7 @@ void createTransData(bContext *C, TransInfo *t)
|
||||
}
|
||||
else if (t->spacetype == SPACE_NLA) {
|
||||
t->flag |= T_POINTS|T_2D_EDIT;
|
||||
// TRANSFORM_FIX_ME
|
||||
//createTransNlaData(C, t);
|
||||
createTransNlaData(C, t);
|
||||
}
|
||||
else if (t->spacetype == SPACE_SEQ) {
|
||||
t->flag |= T_POINTS|T_2D_EDIT;
|
||||
|
||||
@@ -59,9 +59,7 @@
|
||||
//#include "BIF_screen.h"
|
||||
//#include "BIF_mywindow.h"
|
||||
#include "BIF_gl.h"
|
||||
//#include "BIF_editaction.h"
|
||||
//#include "BIF_editmesh.h"
|
||||
//#include "BIF_editnla.h"
|
||||
//#include "BIF_editsima.h"
|
||||
//#include "BIF_editparticle.h"
|
||||
//#include "BIF_meshtools.h"
|
||||
@@ -81,6 +79,7 @@
|
||||
#include "BKE_key.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_modifier.h"
|
||||
#include "BKE_nla.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_utildefines.h"
|
||||
#include "BKE_context.h"
|
||||
@@ -89,6 +88,7 @@
|
||||
#include "ED_armature.h"
|
||||
#include "ED_image.h"
|
||||
#include "ED_keyframing.h"
|
||||
#include "ED_markers.h"
|
||||
#include "ED_mesh.h"
|
||||
#include "ED_retopo.h"
|
||||
#include "ED_space_api.h"
|
||||
@@ -102,6 +102,8 @@
|
||||
#include "BLI_editVert.h"
|
||||
#include "BLI_rand.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
|
||||
#include "WM_types.h"
|
||||
|
||||
#include "UI_resources.h"
|
||||
@@ -268,92 +270,6 @@ void recalcData(TransInfo *t)
|
||||
Scene *scene = t->scene;
|
||||
Base *base;
|
||||
|
||||
#if 0 // TRANSFORM_FIX_ME
|
||||
if (t->spacetype == SPACE_ACTION) {
|
||||
Object *ob= OBACT;
|
||||
void *data;
|
||||
short context;
|
||||
|
||||
/* determine what type of data we are operating on */
|
||||
data = get_action_context(&context);
|
||||
if (data == NULL) return;
|
||||
|
||||
/* always flush data if gpencil context */
|
||||
if (context == ACTCONT_GPENCIL) {
|
||||
flushTransGPactionData(t);
|
||||
}
|
||||
|
||||
if (G.saction->lock) {
|
||||
if (context == ACTCONT_ACTION) {
|
||||
if(ob) {
|
||||
ob->ctime= -1234567.0f;
|
||||
if(ob->pose || ob_get_key(ob))
|
||||
DAG_object_flush_update(G.scene, ob, OB_RECALC);
|
||||
else
|
||||
DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
|
||||
}
|
||||
}
|
||||
else if (context == ACTCONT_SHAPEKEY) {
|
||||
DAG_object_flush_update(G.scene, OBACT, OB_RECALC_OB|OB_RECALC_DATA);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (t->spacetype == SPACE_NLA) {
|
||||
if (G.snla->lock) {
|
||||
for (base=G.scene->base.first; base; base=base->next) {
|
||||
if (base->flag & BA_HAS_RECALC_OB)
|
||||
base->object->recalc |= OB_RECALC_OB;
|
||||
if (base->flag & BA_HAS_RECALC_DATA)
|
||||
base->object->recalc |= OB_RECALC_DATA;
|
||||
|
||||
if (base->object->recalc)
|
||||
base->object->ctime= -1234567.0f; // eveil!
|
||||
|
||||
/* recalculate scale of selected nla-strips */
|
||||
if (base->object->nlastrips.first) {
|
||||
Object *bob= base->object;
|
||||
bActionStrip *strip;
|
||||
|
||||
for (strip= bob->nlastrips.first; strip; strip= strip->next) {
|
||||
if (strip->flag & ACTSTRIP_SELECT) {
|
||||
float actlen= strip->actend - strip->actstart;
|
||||
float len= strip->end - strip->start;
|
||||
|
||||
strip->scale= len / (actlen * strip->repeat);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DAG_scene_flush_update(G.scene, screen_view3d_layers(), 0);
|
||||
}
|
||||
else {
|
||||
for (base=G.scene->base.first; base; base=base->next) {
|
||||
/* recalculate scale of selected nla-strips */
|
||||
if (base->object && base->object->nlastrips.first) {
|
||||
Object *bob= base->object;
|
||||
bActionStrip *strip;
|
||||
|
||||
for (strip= bob->nlastrips.first; strip; strip= strip->next) {
|
||||
if (strip->flag & ACTSTRIP_SELECT) {
|
||||
float actlen= strip->actend - strip->actstart;
|
||||
float len= strip->end - strip->start;
|
||||
|
||||
/* prevent 'negative' scaling */
|
||||
if (len < 0) {
|
||||
SWAP(float, strip->start, strip->end);
|
||||
len= fabs(len);
|
||||
}
|
||||
|
||||
/* calculate new scale */
|
||||
strip->scale= len / (actlen * strip->repeat);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (t->obedit) {
|
||||
}
|
||||
else if(G.f & G_PARTICLEEDIT) {
|
||||
@@ -420,6 +336,179 @@ void recalcData(TransInfo *t)
|
||||
|
||||
}
|
||||
}
|
||||
else if (t->spacetype == SPACE_NLA) {
|
||||
TransDataNla *tdn= (TransDataNla *)t->customData;
|
||||
SpaceNla *snla= (SpaceNla *)t->sa->spacedata.first;
|
||||
Scene *scene= t->scene;
|
||||
double secf= FPS;
|
||||
int i;
|
||||
|
||||
/* for each strip we've got, perform some additional validation of the values that got set before
|
||||
* using RNA to set the value (which does some special operations when setting these values to make
|
||||
* sure that everything works ok)
|
||||
*/
|
||||
for (i = 0; i < t->total; i++, tdn++) {
|
||||
NlaStrip *strip= tdn->strip;
|
||||
PointerRNA strip_ptr;
|
||||
short pExceeded, nExceeded, iter;
|
||||
int delta_y1, delta_y2;
|
||||
|
||||
/* if this tdn has no handles, that means it is just a dummy that should be skipped */
|
||||
if (tdn->handle == 0)
|
||||
continue;
|
||||
|
||||
/* if cancelling transform, just write the values without validating, then move on */
|
||||
if (t->state == TRANS_CANCEL) {
|
||||
/* clear the values by directly overwriting the originals, but also need to restore
|
||||
* endpoints of neighboring transition-strips
|
||||
*/
|
||||
|
||||
/* start */
|
||||
strip->start= tdn->h1[0];
|
||||
|
||||
if ((strip->prev) && (strip->prev->type == NLASTRIP_TYPE_TRANSITION))
|
||||
strip->prev->end= tdn->h1[0];
|
||||
|
||||
/* end */
|
||||
strip->end= tdn->h2[0];
|
||||
|
||||
if ((strip->next) && (strip->next->type == NLASTRIP_TYPE_TRANSITION))
|
||||
strip->next->start= tdn->h2[0];
|
||||
|
||||
/* flush transforms to child strips (since this should be a meta) */
|
||||
BKE_nlameta_flush_transforms(strip);
|
||||
|
||||
/* restore to original track (if needed) */
|
||||
if (tdn->oldTrack != tdn->nlt) {
|
||||
/* just append to end of list for now, since strips get sorted in special_aftertrans_update() */
|
||||
BLI_remlink(&tdn->nlt->strips, strip);
|
||||
BLI_addtail(&tdn->oldTrack->strips, strip);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/* firstly, check if the proposed transform locations would overlap with any neighbouring strips
|
||||
* (barring transitions) which are absolute barriers since they are not being moved
|
||||
*
|
||||
* this is done as a iterative procedure (done 5 times max for now)
|
||||
*/
|
||||
for (iter=0; iter < 5; iter++) {
|
||||
pExceeded= ((strip->prev) && (strip->prev->type != NLASTRIP_TYPE_TRANSITION) && (tdn->h1[0] < strip->prev->end));
|
||||
nExceeded= ((strip->next) && (strip->next->type != NLASTRIP_TYPE_TRANSITION) && (tdn->h2[0] > strip->next->start));
|
||||
|
||||
if ((pExceeded && nExceeded) || (iter == 4) ) {
|
||||
/* both endpoints exceeded (or iteration ping-pong'd meaning that we need a compromise)
|
||||
* - simply crop strip to fit within the bounds of the strips bounding it
|
||||
* - if there were no neighbours, clear the transforms (make it default to the strip's current values)
|
||||
*/
|
||||
if (strip->prev && strip->next) {
|
||||
tdn->h1[0]= strip->prev->end;
|
||||
tdn->h2[0]= strip->next->start;
|
||||
}
|
||||
else {
|
||||
tdn->h1[0]= strip->start;
|
||||
tdn->h2[0]= strip->end;
|
||||
}
|
||||
}
|
||||
else if (nExceeded) {
|
||||
/* move backwards */
|
||||
float offset= tdn->h2[0] - strip->next->start;
|
||||
|
||||
tdn->h1[0] -= offset;
|
||||
tdn->h2[0] -= offset;
|
||||
}
|
||||
else if (pExceeded) {
|
||||
/* more forwards */
|
||||
float offset= strip->prev->end - tdn->h1[0];
|
||||
|
||||
tdn->h1[0] += offset;
|
||||
tdn->h2[0] += offset;
|
||||
}
|
||||
else /* all is fine and well */
|
||||
break;
|
||||
}
|
||||
|
||||
/* handle auto-snapping */
|
||||
switch (snla->autosnap) {
|
||||
case SACTSNAP_FRAME: /* snap to nearest frame/time */
|
||||
if (snla->flag & SNLA_DRAWTIME) {
|
||||
tdn->h1[0]= (float)( floor((tdn->h1[0]/secf) + 0.5f) * secf );
|
||||
tdn->h2[0]= (float)( floor((tdn->h2[0]/secf) + 0.5f) * secf );
|
||||
}
|
||||
else {
|
||||
tdn->h1[0]= (float)( floor(tdn->h1[0]+0.5f) );
|
||||
tdn->h2[0]= (float)( floor(tdn->h2[0]+0.5f) );
|
||||
}
|
||||
break;
|
||||
|
||||
case SACTSNAP_MARKER: /* snap to nearest marker */
|
||||
tdn->h1[0]= (float)ED_markers_find_nearest_marker_time(&t->scene->markers, tdn->h1[0]);
|
||||
tdn->h2[0]= (float)ED_markers_find_nearest_marker_time(&t->scene->markers, tdn->h2[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
/* use RNA to write the values... */
|
||||
// TODO: do we need to write in 2 passes to make sure that no truncation goes on?
|
||||
RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr);
|
||||
|
||||
RNA_float_set(&strip_ptr, "start_frame", tdn->h1[0]);
|
||||
RNA_float_set(&strip_ptr, "end_frame", tdn->h2[0]);
|
||||
|
||||
/* flush transforms to child strips (since this should be a meta) */
|
||||
BKE_nlameta_flush_transforms(strip);
|
||||
|
||||
|
||||
/* now, check if we need to try and move track
|
||||
* - we need to calculate both, as only one may have been altered by transform if only 1 handle moved
|
||||
*/
|
||||
delta_y1= ((int)tdn->h1[1] / NLACHANNEL_STEP - tdn->trackIndex);
|
||||
delta_y2= ((int)tdn->h2[1] / NLACHANNEL_STEP - tdn->trackIndex);
|
||||
|
||||
if (delta_y1 || delta_y2) {
|
||||
NlaTrack *track;
|
||||
int delta = (delta_y2) ? delta_y2 : delta_y1;
|
||||
int n;
|
||||
|
||||
/* move in the requested direction, checking at each layer if there's space for strip to pass through,
|
||||
* stopping on the last track available or that we're able to fit in
|
||||
*/
|
||||
if (delta > 0) {
|
||||
for (track=tdn->nlt->next, n=0; (track) && (n < delta); track=track->next, n++) {
|
||||
/* check if space in this track for the strip */
|
||||
if (BKE_nlatrack_has_space(track, strip->start, strip->end)) {
|
||||
/* move strip to this track */
|
||||
BLI_remlink(&tdn->nlt->strips, strip);
|
||||
BKE_nlatrack_add_strip(track, strip);
|
||||
|
||||
tdn->nlt= track;
|
||||
tdn->trackIndex += (n + 1); /* + 1, since n==0 would mean that we didn't change track */
|
||||
}
|
||||
else /* can't move any further */
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* make delta 'positive' before using it, since we now know to go backwards */
|
||||
delta= -delta;
|
||||
|
||||
for (track=tdn->nlt->prev, n=0; (track) && (n < delta); track=track->prev, n++) {
|
||||
/* check if space in this track for the strip */
|
||||
if (BKE_nlatrack_has_space(track, strip->start, strip->end)) {
|
||||
/* move strip to this track */
|
||||
BLI_remlink(&tdn->nlt->strips, strip);
|
||||
BKE_nlatrack_add_strip(track, strip);
|
||||
|
||||
tdn->nlt= track;
|
||||
tdn->trackIndex -= (n - 1); /* - 1, since n==0 would mean that we didn't change track */
|
||||
}
|
||||
else /* can't move any further */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (t->obedit) {
|
||||
if ELEM(t->obedit->type, OB_CURVE, OB_SURF) {
|
||||
Curve *cu= t->obedit->data;
|
||||
@@ -867,7 +956,7 @@ void postTrans (TransInfo *t)
|
||||
if(sima->flag & SI_LIVE_UNWRAP)
|
||||
ED_uvedit_live_unwrap_end(t->state == TRANS_CANCEL);
|
||||
}
|
||||
else if(t->spacetype==SPACE_ACTION) {
|
||||
else if(ELEM(t->spacetype, SPACE_ACTION, SPACE_NLA)) {
|
||||
if (t->customData)
|
||||
MEM_freeN(t->customData);
|
||||
}
|
||||
|
||||
@@ -634,6 +634,19 @@ void transform_keymap_for_space(struct wmWindowManager *wm, struct ListBase *key
|
||||
|
||||
km = WM_keymap_add_item(keymap, "TFM_OT_resize", SKEY, KM_PRESS, 0, 0);
|
||||
break;
|
||||
case SPACE_NLA:
|
||||
km= WM_keymap_add_item(keymap, "TFM_OT_transform", GKEY, KM_PRESS, 0, 0);
|
||||
RNA_int_set(km->ptr, "mode", TFM_TRANSLATION);
|
||||
|
||||
km= WM_keymap_add_item(keymap, "TFM_OT_transform", EVT_TWEAK_S, KM_ANY, 0, 0);
|
||||
RNA_int_set(km->ptr, "mode", TFM_TRANSLATION);
|
||||
|
||||
km= WM_keymap_add_item(keymap, "TFM_OT_transform", EKEY, KM_PRESS, 0, 0);
|
||||
RNA_int_set(km->ptr, "mode", TFM_TIME_EXTEND);
|
||||
|
||||
km= WM_keymap_add_item(keymap, "TFM_OT_transform", SKEY, KM_PRESS, 0, 0);
|
||||
RNA_int_set(km->ptr, "mode", TFM_TIME_SCALE);
|
||||
break;
|
||||
case SPACE_NODE:
|
||||
km= WM_keymap_add_item(keymap, "TFM_OT_translation", GKEY, KM_PRESS, 0, 0);
|
||||
|
||||
|
||||
@@ -225,10 +225,18 @@ typedef struct bActionGroup {
|
||||
|
||||
/* Action Group flags */
|
||||
typedef enum eActionGroup_Flag {
|
||||
/* group is selected */
|
||||
AGRP_SELECTED = (1<<0),
|
||||
/* group is 'active' / last selected one */
|
||||
AGRP_ACTIVE = (1<<1),
|
||||
/* keyframes/channels belonging to it cannot be edited */
|
||||
AGRP_PROTECTED = (1<<2),
|
||||
/* for UI, sub-channels are shown */
|
||||
AGRP_EXPANDED = (1<<3),
|
||||
/* sub-channels are not evaluated */
|
||||
AGRP_MUTED = (1<<4),
|
||||
/* sub-channels are not visible in Graph Editor */
|
||||
AGRP_NOTVISIBLE = (1<<5),
|
||||
|
||||
AGRP_TEMP = (1<<30),
|
||||
AGRP_MOVED = (1<<31)
|
||||
@@ -269,6 +277,7 @@ typedef enum eAction_Flags {
|
||||
/* flags for evaluation/editing */
|
||||
ACT_MUTED = (1<<9),
|
||||
ACT_PROTECTED = (1<<10),
|
||||
ACT_DISABLED = (1<<11),
|
||||
} eAction_Flags;
|
||||
|
||||
|
||||
@@ -288,8 +297,10 @@ typedef struct bDopeSheet {
|
||||
/* DopeSheet filter-flag */
|
||||
typedef enum DOPESHEET_FILTERFLAG {
|
||||
/* general filtering */
|
||||
ADS_FILTER_ONLYSEL = (1<<0),
|
||||
ADS_FILTER_ONLYDRIVERS = (1<<1),
|
||||
ADS_FILTER_ONLYSEL = (1<<0), /* only include channels relating to selected data */
|
||||
|
||||
ADS_FILTER_ONLYDRIVERS = (1<<1), /* for 'Drivers' editor - only include Driver data from AnimData */
|
||||
ADS_FILTER_ONLYNLA = (1<<2), /* for 'NLA' editor - only include NLA data from AnimData */
|
||||
|
||||
/* datatype-based filtering */
|
||||
ADS_FILTER_NOSHAPEKEYS = (1<<6),
|
||||
@@ -300,9 +311,11 @@ typedef enum DOPESHEET_FILTERFLAG {
|
||||
ADS_FILTER_NOWOR = (1<<14),
|
||||
ADS_FILTER_NOSCE = (1<<15),
|
||||
|
||||
/* NLA-specific filters */
|
||||
ADS_FILTER_NLA_NOACT = (1<<20), /* if the AnimData block has no NLA data, don't include to just show Action-line */
|
||||
|
||||
/* combination filters (some only used at runtime) */
|
||||
ADS_FILTER_NOOBDATA = (ADS_FILTER_NOCAM|ADS_FILTER_NOMAT|ADS_FILTER_NOLAM|ADS_FILTER_NOCUR),
|
||||
ADS_FILTER_NLADUMMY = (ADS_FILTER_NOSHAPEKEYS|ADS_FILTER_NOOBDATA),
|
||||
} DOPESHEET_FILTERFLAG;
|
||||
|
||||
/* DopeSheet general flags */
|
||||
|
||||
@@ -1,5 +1,28 @@
|
||||
/* Testing code for new animation system in 2.5
|
||||
* Copyright 2009, Joshua Leung
|
||||
/**
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
|
||||
* All rights reserved.
|
||||
*
|
||||
* Contributor(s): Joshua Leung (full recode)
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#ifndef DNA_ANIM_TYPES_H
|
||||
@@ -43,9 +66,10 @@ typedef struct FModifier {
|
||||
enum {
|
||||
FMODIFIER_TYPE_NULL = 0,
|
||||
FMODIFIER_TYPE_GENERATOR,
|
||||
FMODIFIER_TYPE_FN_GENERATOR,
|
||||
FMODIFIER_TYPE_ENVELOPE,
|
||||
FMODIFIER_TYPE_CYCLES,
|
||||
FMODIFIER_TYPE_NOISE, /* unimplemented - generate variations using some basic noise generator... */
|
||||
FMODIFIER_TYPE_NOISE,
|
||||
FMODIFIER_TYPE_FILTER, /* unimplemented - for applying: fft, high/low pass filters, etc. */
|
||||
FMODIFIER_TYPE_PYTHON,
|
||||
FMODIFIER_TYPE_LIMITS,
|
||||
@@ -68,39 +92,55 @@ enum {
|
||||
|
||||
/* --- */
|
||||
|
||||
/* generator modifier data */
|
||||
/* Generator modifier data */
|
||||
typedef struct FMod_Generator {
|
||||
/* generator based on PyExpression */
|
||||
char expression[256]; /* python expression to use as generator */
|
||||
|
||||
/* general generator information */
|
||||
float *coefficients; /* coefficients array */
|
||||
unsigned int arraysize; /* size of the coefficients array */
|
||||
|
||||
short poly_order; /* order of polynomial generated (i.e. 1 for linear, 2 for quadratic) */
|
||||
short func_type; /* builtin math function eFMod_Generator_Functions */
|
||||
|
||||
int pad;
|
||||
int poly_order; /* order of polynomial generated (i.e. 1 for linear, 2 for quadratic) */
|
||||
int mode; /* which 'generator' to use eFMod_Generator_Modes */
|
||||
|
||||
/* settings */
|
||||
short flag; /* settings */
|
||||
short mode; /* which 'generator' to use eFMod_Generator_Modes */
|
||||
int flag; /* settings */
|
||||
} FMod_Generator;
|
||||
|
||||
/* generator modes */
|
||||
enum {
|
||||
FCM_GENERATOR_POLYNOMIAL = 0,
|
||||
FCM_GENERATOR_POLYNOMIAL_FACTORISED,
|
||||
FCM_GENERATOR_FUNCTION,
|
||||
FCM_GENERATOR_EXPRESSION,
|
||||
} eFMod_Generator_Modes;
|
||||
|
||||
/* generator flags */
|
||||
|
||||
/* generator flags
|
||||
* - shared by Generator and Function Generator
|
||||
*/
|
||||
enum {
|
||||
/* generator works in conjunction with other modifiers (i.e. doesn't replace those before it) */
|
||||
FCM_GENERATOR_ADDITIVE = (1<<0),
|
||||
} eFMod_Generator_Flags;
|
||||
|
||||
|
||||
/* 'Built-In Function' Generator modifier data
|
||||
*
|
||||
* This uses the general equation for equations:
|
||||
* y = amplitude * fn(phase_multiplier*x + phase_offset) + y_offset
|
||||
*
|
||||
* where amplitude, phase_multiplier/offset, y_offset are user-defined coefficients,
|
||||
* x is the evaluation 'time', and 'y' is the resultant value
|
||||
*/
|
||||
typedef struct FMod_FunctionGenerator {
|
||||
/* coefficients for general equation (as above) */
|
||||
float amplitude;
|
||||
float phase_multiplier;
|
||||
float phase_offset;
|
||||
float value_offset;
|
||||
|
||||
/* flags */
|
||||
int type; /* eFMod_Generator_Functions */
|
||||
int flag; /* eFMod_Generator_flags */
|
||||
} FMod_FunctionGenerator;
|
||||
|
||||
/* 'function' generator types */
|
||||
enum {
|
||||
FCM_GENERATOR_FN_SIN = 0,
|
||||
@@ -108,6 +148,7 @@ enum {
|
||||
FCM_GENERATOR_FN_TAN,
|
||||
FCM_GENERATOR_FN_SQRT,
|
||||
FCM_GENERATOR_FN_LN,
|
||||
FCM_GENERATOR_FN_SINC,
|
||||
} eFMod_Generator_Functions;
|
||||
|
||||
|
||||
@@ -386,85 +427,104 @@ typedef struct AnimMapper {
|
||||
|
||||
/* ************************************************ */
|
||||
/* NLA - Non-Linear Animation */
|
||||
// TODO: the concepts here still need to be refined to solve any unresolved items
|
||||
|
||||
/* NLA Modifiers ---------------------------------- */
|
||||
|
||||
/* These differ from F-Curve modifiers, as although F-Curve modifiers also operate on a
|
||||
* per-channel basis too (in general), they are part of the animation data itself, which
|
||||
* means that their effects are inherited by all of their users. In order to counteract this,
|
||||
* the modifiers here should be used to provide variation to pre-created motions only.
|
||||
*/
|
||||
|
||||
/* NLA Strips ------------------------------------- */
|
||||
|
||||
/* NLA Strip (strip)
|
||||
*
|
||||
* A NLA Strip is a container for the reuse of Action data, defining parameters
|
||||
* to control the remapping of the Action data to some destination. Actions being
|
||||
* referenced by NLA-Strips SHOULD-NOT be editable, unless they were created in such
|
||||
* a way that results in very little mapping distortion (i.e. for layered animation only,
|
||||
* opposed to prebuilt 'blocks' which are quickly dumped into the NLA for crappymatic machima-type
|
||||
* stuff)
|
||||
* to control the remapping of the Action data to some destination.
|
||||
*/
|
||||
typedef struct NlaStrip {
|
||||
struct NlaStrip *next, *prev;
|
||||
|
||||
bAction *act; /* Action that is referenced by this strip */
|
||||
ListBase strips; /* 'Child' strips (used for 'meta' strips) */
|
||||
bAction *act; /* Action that is referenced by this strip (strip is 'user' of the action) */
|
||||
AnimMapper *remap; /* Remapping info this strip (for tweaking correspondance of action with context) */
|
||||
|
||||
ListBase modifiers; /* NLA Modifiers */
|
||||
ListBase fcurves; /* F-Curves for controlling this strip's influence and timing */ // TODO: move out?
|
||||
ListBase modifiers; /* F-Curve modifiers to be applied to the entire strip's referenced F-Curves */
|
||||
|
||||
char name[64]; /* User-Visible Identifier for Strip */
|
||||
|
||||
ListBase fcurves; /* F-Curves for controlling this strip's influence and timing */
|
||||
float influence; /* Influence of strip */
|
||||
float act_time; /* Current 'time' within action being used */
|
||||
float strip_time; /* Current 'time' within action being used (automatically evaluated, but can be overridden) */
|
||||
|
||||
float start, end; /* extents of the strip */
|
||||
float actstart, actend; /* range of the action to use */
|
||||
|
||||
float repeat; /* The number of times to repeat the action range (only when no F-Curves) */
|
||||
float scale; /* The amount the action range is scaled by (only when no F-Curves) */
|
||||
float repeat; /* The number of times to repeat the action range (only when no F-Curves) */
|
||||
float scale; /* The amount the action range is scaled by (only when no F-Curves) */
|
||||
|
||||
float blendin, blendout; /* strip blending length (only used when there are no F-Curves) */
|
||||
int blendmode; /* strip blending mode */
|
||||
short blendmode; /* strip blending mode (layer-based mixing) */
|
||||
short extendmode; /* strip extrapolation mode (time-based mixing) */
|
||||
|
||||
int flag; /* settings */
|
||||
|
||||
// umm... old unused cruft?
|
||||
int stride_axis; /* axis for stridebone stuff - 0=x, 1=y, 2=z */
|
||||
int pad;
|
||||
|
||||
float actoffs; /* Offset within action, for cycles and striding (only set for ACT_USESTRIDE) */
|
||||
float stridelen; /* The stridelength (considered when flag & ACT_USESTRIDE) */
|
||||
|
||||
char stridechannel[32]; /* Instead of stridelen, it uses an action channel */
|
||||
char offs_bone[32]; /* if repeat, use this bone/channel for defining offset */
|
||||
short flag; /* settings */
|
||||
short type; /* type of NLA strip */
|
||||
} NlaStrip;
|
||||
|
||||
/* NLA Strip Blending Mode */
|
||||
enum {
|
||||
NLASTRIPMODE_BLEND = 0,
|
||||
NLASTRIPMODE_ADD,
|
||||
NLASTRIPMODE_SUBTRACT,
|
||||
} eActStrip_Mode;
|
||||
NLASTRIP_MODE_REPLACE = 0,
|
||||
NLASTRIP_MODE_ADD,
|
||||
NLASTRIP_MODE_SUBTRACT,
|
||||
NLASTRIP_MODE_MULTIPLY,
|
||||
} eNlaStrip_Blend_Mode;
|
||||
|
||||
/* NLA Strip Extrpolation Mode */
|
||||
enum {
|
||||
/* extend before first frame if no previous strips in track, and always hold+extend last frame */
|
||||
NLASTRIP_EXTEND_HOLD = 0,
|
||||
/* only hold+extend last frame */
|
||||
NLASTRIP_EXTEND_HOLD_FORWARD,
|
||||
/* don't contribute at all */
|
||||
NLASTRIP_EXTEND_NOTHING,
|
||||
} eNlaStrip_Extrapolate_Mode;
|
||||
|
||||
/* NLA Strip Settings */
|
||||
// TODO: check on which of these are still useful...
|
||||
enum {
|
||||
NLASTRIP_SELECT = (1<<0),
|
||||
NLASTRIP_USESTRIDE = (1<<1),
|
||||
NLASTRIP_BLENDTONEXT = (1<<2), /* Not implemented. Is not used anywhere */
|
||||
NLASTRIP_HOLDLASTFRAME = (1<<3),
|
||||
NLASTRIP_ACTIVE = (1<<4),
|
||||
NLASTRIP_LOCK_ACTION = (1<<5),
|
||||
NLASTRIP_MUTE = (1<<6),
|
||||
NLASTRIP_REVERSE = (1<<7), /* This has yet to be implemented. To indicate that a strip should be played backwards */
|
||||
NLASTRIP_CYCLIC_USEX = (1<<8),
|
||||
NLASTRIP_CYCLIC_USEY = (1<<9),
|
||||
NLASTRIP_CYCLIC_USEZ = (1<<10),
|
||||
NLASTRIP_AUTO_BLENDS = (1<<11),
|
||||
NLASTRIP_TWEAK = (1<<12), /* This strip is a tweaking strip (only set if owner track is a tweak track) */
|
||||
} eActionStrip_Flag;
|
||||
/* UI selection flags */
|
||||
/* NLA strip is the active one in the track (also indicates if strip is being tweaked) */
|
||||
NLASTRIP_FLAG_ACTIVE = (1<<0),
|
||||
/* NLA strip is selected for editing */
|
||||
NLASTRIP_FLAG_SELECT = (1<<1),
|
||||
// NLASTRIP_FLAG_SELECT_L = (1<<2), // left handle selected
|
||||
// NLASTRIP_FLAG_SELECT_R = (1<<3), // right handle selected
|
||||
/* NLA strip uses the same action that the action being tweaked uses (not set for the twaking one though) */
|
||||
NLASTRIP_FLAG_TWEAKUSER = (1<<4),
|
||||
|
||||
/* controls driven by local F-Curves */
|
||||
/* strip influence is controlled by local F-Curve */
|
||||
NLASTRIP_FLAG_USR_INFLUENCE = (1<<5),
|
||||
NLASTRIP_FLAG_USR_TIME = (1<<6),
|
||||
|
||||
/* playback flags (may be overriden by F-Curves) */
|
||||
/* NLA strip blendin/out values are set automatically based on overlaps */
|
||||
NLASTRIP_FLAG_AUTO_BLENDS = (1<<10),
|
||||
/* NLA strip is played back in reverse order */
|
||||
NLASTRIP_FLAG_REVERSE = (1<<11),
|
||||
/* NLA strip is muted (i.e. doesn't contribute in any way) */
|
||||
// TODO: this overlaps a lot with the functionality in track
|
||||
NLASTRIP_FLAG_MUTED = (1<<12),
|
||||
/* NLA strip length is synced to the length of the referenced action */
|
||||
NLASTRIP_FLAG_SYNC_LENGTH = (1<<13),
|
||||
|
||||
/* temporary editing flags */
|
||||
/* NLA-Strip is really just a temporary meta used to facilitate easier transform code */
|
||||
NLASTRIP_FLAG_TEMP_META = (1<<14),
|
||||
NLASTRIP_FLAG_EDIT_TOUCHED = (1<<15),
|
||||
} eNlaStrip_Flag;
|
||||
|
||||
/* NLA Strip Type */
|
||||
enum {
|
||||
/* 'clip' - references an Action */
|
||||
NLASTRIP_TYPE_CLIP = 0,
|
||||
/* 'transition' - blends between the adjacent strips */
|
||||
NLASTRIP_TYPE_TRANSITION,
|
||||
/* 'meta' - a strip which acts as a container for a few others */
|
||||
NLASTRIP_TYPE_META,
|
||||
} eNlaStrip_Type;
|
||||
|
||||
/* NLA Tracks ------------------------------------- */
|
||||
|
||||
@@ -483,14 +543,12 @@ typedef struct NlaTrack {
|
||||
int flag; /* settings for this track */
|
||||
int index; /* index of the track in the stack (NOTE: not really useful, but we need a pad var anyways!) */
|
||||
|
||||
char info[64]; /* short user-description of this track */
|
||||
char name[64]; /* short user-description of this track */
|
||||
} NlaTrack;
|
||||
|
||||
/* settings for track */
|
||||
enum {
|
||||
/* track is the one that settings can be modified on (doesn't indicate
|
||||
* that it's for 'tweaking' though)
|
||||
*/
|
||||
/* track is the one that settings can be modified on, also indicates if track is being 'tweaked' */
|
||||
NLATRACK_ACTIVE = (1<<0),
|
||||
/* track is selected in UI for relevant editing operations */
|
||||
NLATRACK_SELECTED = (1<<1),
|
||||
@@ -500,10 +558,9 @@ enum {
|
||||
NLATRACK_SOLO = (1<<3),
|
||||
/* track's settings (and strips) cannot be edited (to guard against unwanted changes) */
|
||||
NLATRACK_PROTECTED = (1<<4),
|
||||
/* strip is the 'last' one that should be evaluated, as the active action
|
||||
* is being used to tweak the animation of the strips up to here
|
||||
*/
|
||||
NLATRACK_TWEAK = (1<<5),
|
||||
|
||||
/* track is not allowed to execute, usually as result of tweaking being enabled (internal flag) */
|
||||
NLATRACK_DISABLED = (1<<10),
|
||||
} eNlaTrack_Flag;
|
||||
|
||||
|
||||
@@ -646,11 +703,15 @@ typedef struct AnimOverride {
|
||||
* blocks may override local settings.
|
||||
*
|
||||
* This datablock should be placed immediately after the ID block where it is used, so that
|
||||
* the code which retrieves this data can do so in an easier manner. See blenkernel/internal/anim_sys.c for details.
|
||||
* the code which retrieves this data can do so in an easier manner. See blenkernel/intern/anim_sys.c for details.
|
||||
*/
|
||||
typedef struct AnimData {
|
||||
/* active action - acts as the 'tweaking track' for the NLA */
|
||||
bAction *action;
|
||||
bAction *action;
|
||||
/* temp-storage for the 'real' active action (i.e. the one used before the tweaking-action
|
||||
* took over to be edited in the Animation Editors)
|
||||
*/
|
||||
bAction *tmpact;
|
||||
/* remapping-info for active action - should only be used if needed
|
||||
* (for 'foreign' actions that aren't working correctly)
|
||||
*/
|
||||
@@ -658,6 +719,8 @@ typedef struct AnimData {
|
||||
|
||||
/* nla-tracks */
|
||||
ListBase nla_tracks;
|
||||
/* active NLA-strip (only set/used during tweaking, so no need to worry about dangling pointers) */
|
||||
NlaStrip *actstrip;
|
||||
|
||||
/* 'drivers' for this ID-block's settings - FCurves, but are completely
|
||||
* separate from those for animation data
|
||||
@@ -676,11 +739,20 @@ enum {
|
||||
ADT_NLA_SOLO_TRACK = (1<<0),
|
||||
/* don't use NLA */
|
||||
ADT_NLA_EVAL_OFF = (1<<1),
|
||||
/* don't execute drivers */
|
||||
ADT_DRIVERS_DISABLED = (1<<2),
|
||||
/* NLA is being 'tweaked' (i.e. in EditMode) */
|
||||
ADT_NLA_EDIT_ON = (1<<2),
|
||||
/* active Action for 'tweaking' does not have mapping applied for editing */
|
||||
ADT_NLA_EDIT_NOMAP = (1<<3),
|
||||
/* NLA-Strip F-Curves are expanded in UI */
|
||||
ADT_NLA_SKEYS_COLLAPSED = (1<<4),
|
||||
|
||||
/* drivers expanded in UI */
|
||||
ADT_DRIVERS_COLLAPSED = (1<<10),
|
||||
/* don't execute drivers */
|
||||
ADT_DRIVERS_DISABLED = (1<<11),
|
||||
|
||||
/* F-Curves from this AnimData block are not visible in the Graph Editor */
|
||||
ADT_CURVES_NOT_VISIBLE = (1<<16),
|
||||
} eAnimData_Flag;
|
||||
|
||||
/* Animation Data recalculation settings (to be set by depsgraph) */
|
||||
|
||||
@@ -148,7 +148,7 @@ typedef struct Curve {
|
||||
ListBase *editnurb; /* edited data, not in file, use pointer so we can check for it */
|
||||
|
||||
struct Object *bevobj, *taperobj, *textoncurve;
|
||||
struct Ipo *ipo;
|
||||
struct Ipo *ipo; // XXX depreceated... old animation system
|
||||
Path *path;
|
||||
struct Key *key;
|
||||
struct Material **mat;
|
||||
@@ -193,7 +193,8 @@ typedef struct Curve {
|
||||
|
||||
int sepchar;
|
||||
|
||||
int totbox, actbox, pad;
|
||||
float ctime; /* current evaltime - for use by Objects parented to curves */
|
||||
int totbox, actbox;
|
||||
struct TextBox *tb;
|
||||
|
||||
int selstart, selend;
|
||||
|
||||
@@ -783,6 +783,10 @@ typedef struct Scene {
|
||||
#define MINFRAME 1
|
||||
#define MINFRAMEF 1.0f
|
||||
|
||||
/* (minimum frame number for current-frame) */
|
||||
#define MINAFRAME -300000
|
||||
#define MINAFRAMEF -300000.0f
|
||||
|
||||
/* depricate this! */
|
||||
#define TESTBASE(v3d, base) ( ((base)->flag & SELECT) && ((base)->lay & v3d->lay) && (((base)->object->restrictflag & OB_RESTRICT_VIEW)==0) )
|
||||
#define TESTBASELIB(v3d, base) ( ((base)->flag & SELECT) && ((base)->lay & v3d->lay) && ((base)->object->id.lib==0) && (((base)->object->restrictflag & OB_RESTRICT_VIEW)==0))
|
||||
@@ -851,6 +855,7 @@ typedef struct Scene {
|
||||
/* sce->flag */
|
||||
#define SCE_DS_SELECTED (1<<0)
|
||||
#define SCE_DS_COLLAPSED (1<<1)
|
||||
#define SCE_NLA_EDIT_ON (1<<2)
|
||||
|
||||
|
||||
/* return flag next_object function */
|
||||
|
||||
@@ -96,10 +96,6 @@ typedef struct SpaceIpo {
|
||||
short blockhandler[8];
|
||||
View2D v2d; /* depricated, copied to region */
|
||||
|
||||
// 'IPO keys' - vertical lines for editing multiple keyframes at once - use Dopesheet instead for this?
|
||||
//ListBase ipokey; // XXX it's not clear how these will come back yet
|
||||
//short showkey; // XXX this doesn't need to be restored until ipokeys come back
|
||||
|
||||
struct bDopeSheet *ads; /* settings for filtering animation data (NOTE: we use a pointer due to code-linking issues) */
|
||||
|
||||
ListBase ghostCurves; /* sampled snapshots of F-Curves used as in-session guides */
|
||||
@@ -107,7 +103,7 @@ typedef struct SpaceIpo {
|
||||
short mode; /* mode for the Graph editor (eGraphEdit_Mode) */
|
||||
short flag; /* settings for Graph editor */
|
||||
short autosnap; /* time-transform autosnapping settings for Graph editor (eAnimEdit_AutoSnap in DNA_action_types.h) */
|
||||
char pin, lock;
|
||||
char pin, lock; // XXX old, unused vars that are probably going to be depreceated soon...
|
||||
} SpaceIpo;
|
||||
|
||||
typedef struct SpaceButs {
|
||||
@@ -276,10 +272,11 @@ typedef struct SpaceNla {
|
||||
|
||||
short blockhandler[8];
|
||||
|
||||
short menunr, lock;
|
||||
short autosnap; /* this uses the same settings as autosnap for Action Editor */
|
||||
short flag;
|
||||
int pad;
|
||||
|
||||
struct bDopeSheet *ads;
|
||||
View2D v2d; /* depricated, copied to region */
|
||||
} SpaceNla;
|
||||
|
||||
@@ -751,8 +748,11 @@ enum {
|
||||
#define IMS_INFILESLI 4
|
||||
|
||||
/* nla->flag */
|
||||
// depreceated
|
||||
#define SNLA_ALLKEYED (1<<0)
|
||||
// depreceated
|
||||
#define SNLA_ACTIVELAYERS (1<<1)
|
||||
|
||||
#define SNLA_DRAWTIME (1<<2)
|
||||
#define SNLA_NOTRANSKEYCULL (1<<3)
|
||||
#define SNLA_NODRAWCFRANUM (1<<4)
|
||||
|
||||
@@ -174,12 +174,14 @@ extern StructRNA RNA_ExplodeModifier;
|
||||
extern StructRNA RNA_ExpressionController;
|
||||
extern StructRNA RNA_Event;
|
||||
extern StructRNA RNA_FCurve;
|
||||
extern StructRNA RNA_FCurveSample;
|
||||
extern StructRNA RNA_FileSelectParams;
|
||||
extern StructRNA RNA_FModifier;
|
||||
extern StructRNA RNA_FModifierCycles;
|
||||
extern StructRNA RNA_FModifierEnvelope;
|
||||
extern StructRNA RNA_FModifierEnvelopeControlPoint;
|
||||
extern StructRNA RNA_FModifierFunctionGenerator;
|
||||
extern StructRNA RNA_FModifierGenerator;
|
||||
extern StructRNA RNA_FModifierGenerator_Function;
|
||||
extern StructRNA RNA_FModifierGenerator_PolyExpanded;
|
||||
extern StructRNA RNA_FModifierLimits;
|
||||
extern StructRNA RNA_FModifierNoise;
|
||||
@@ -274,6 +276,8 @@ extern StructRNA RNA_MultiresModifier;
|
||||
extern StructRNA RNA_MusgraveTexture;
|
||||
extern StructRNA RNA_NandController;
|
||||
extern StructRNA RNA_NearSensor;
|
||||
extern StructRNA RNA_NlaTrack;
|
||||
extern StructRNA RNA_NlaStrip;
|
||||
extern StructRNA RNA_Node;
|
||||
extern StructRNA RNA_NodeTree;
|
||||
extern StructRNA RNA_NoiseTexture;
|
||||
@@ -366,7 +370,10 @@ extern StructRNA RNA_SoundSequence;
|
||||
extern StructRNA RNA_Space;
|
||||
extern StructRNA RNA_Space3DView;
|
||||
extern StructRNA RNA_SpaceButtonsWindow;
|
||||
extern StructRNA RNA_SpaceDopeSheetEditor;
|
||||
extern StructRNA RNA_SpaceGraphEditor;
|
||||
extern StructRNA RNA_SpaceImageEditor;
|
||||
extern StructRNA RNA_SpaceNLA;
|
||||
extern StructRNA RNA_SpaceOutliner;
|
||||
extern StructRNA RNA_SpaceSequenceEditor;
|
||||
extern StructRNA RNA_SpaceTextEditor;
|
||||
|
||||
@@ -1921,6 +1921,7 @@ RNAProcessItem PROCESS_ITEMS[]= {
|
||||
{"rna_mesh.c", "rna_mesh_api.c", RNA_def_mesh},
|
||||
{"rna_meta.c", NULL, RNA_def_meta},
|
||||
{"rna_modifier.c", NULL, RNA_def_modifier},
|
||||
{"rna_nla.c", NULL, RNA_def_nla},
|
||||
{"rna_nodetree.c", NULL, RNA_def_nodetree},
|
||||
{"rna_object.c", "rna_object_api.c", RNA_def_object},
|
||||
{"rna_object_force.c", NULL, RNA_def_object_force},
|
||||
|
||||
@@ -184,7 +184,7 @@ void rna_def_animdata(BlenderRNA *brna)
|
||||
/* NLA */
|
||||
prop= RNA_def_property(srna, "nla_tracks", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_collection_sdna(prop, NULL, "nla_tracks", NULL);
|
||||
RNA_def_property_struct_type(prop, "UnknownType"); // XXX!
|
||||
RNA_def_property_struct_type(prop, "NlaTrack");
|
||||
RNA_def_property_ui_text(prop, "NLA Tracks", "NLA Tracks (i.e. Animation Layers).");
|
||||
|
||||
/* Action */
|
||||
|
||||
@@ -728,13 +728,13 @@ static void rna_def_constraint_action(BlenderRNA *brna)
|
||||
|
||||
prop= RNA_def_property(srna, "start_frame", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "start");
|
||||
RNA_def_property_range(prop, MINFRAME, MAXFRAME);
|
||||
RNA_def_property_range(prop, MINAFRAME, MAXFRAME);
|
||||
RNA_def_property_ui_text(prop, "Start Frame", "First frame of the Action to use.");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update");
|
||||
|
||||
prop= RNA_def_property(srna, "end_frame", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "end");
|
||||
RNA_def_property_range(prop, MINFRAME, MAXFRAME);
|
||||
RNA_def_property_range(prop, MINAFRAME, MAXFRAME);
|
||||
RNA_def_property_ui_text(prop, "End Frame", "Last frame of the Action to use.");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update");
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
|
||||
#include "DNA_curve_types.h"
|
||||
#include "DNA_material_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
EnumPropertyItem beztriple_handle_type_items[] = {
|
||||
{HD_FREE, "FREE", 0, "Free", ""},
|
||||
@@ -558,6 +559,11 @@ static void rna_def_curve(BlenderRNA *brna)
|
||||
RNA_def_property_ui_range(prop, 1, 1024, 1, 0);
|
||||
RNA_def_property_ui_text(prop, "Render Resolution V", "Surface resolution in V direction used while rendering. Zero skips this property.");
|
||||
|
||||
|
||||
prop= RNA_def_property(srna, "eval_time", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "ctime");
|
||||
RNA_def_property_ui_text(prop, "Evaluation Time", "Parametric position along the length of the curve that Objects 'following' it should be at.");
|
||||
|
||||
/* pointers */
|
||||
prop= RNA_def_property(srna, "bevel_object", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_pointer_sdna(prop, NULL, "bevobj");
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
EnumPropertyItem fmodifier_type_items[] = {
|
||||
{FMODIFIER_TYPE_NULL, "NULL", 0, "Invalid", ""},
|
||||
{FMODIFIER_TYPE_GENERATOR, "GENERATOR", 0, "Generator", ""},
|
||||
{FMODIFIER_TYPE_FN_GENERATOR, "FNGENERATOR", 0, "Built-In Function", ""},
|
||||
{FMODIFIER_TYPE_ENVELOPE, "ENVELOPE", 0, "Envelope", ""},
|
||||
{FMODIFIER_TYPE_CYCLES, "CYCLES", 0, "Cycles", ""},
|
||||
{FMODIFIER_TYPE_NOISE, "NOISE", 0, "Noise", ""},
|
||||
@@ -47,62 +48,6 @@ EnumPropertyItem fmodifier_type_items[] = {
|
||||
|
||||
#ifdef RNA_RUNTIME
|
||||
|
||||
float FModGenFunc_amplitude_get(PointerRNA *ptr)
|
||||
{
|
||||
FModifier *fcm = (FModifier *)(ptr->data);
|
||||
FMod_Generator *data= (FMod_Generator*)(fcm->data);
|
||||
return (data->coefficients) ? (float)data->coefficients[0] : 1.0f;
|
||||
}
|
||||
|
||||
void FModGenFunc_amplitude_set(PointerRNA *ptr, float value)
|
||||
{
|
||||
FModifier *fcm = (FModifier *)(ptr->data);
|
||||
FMod_Generator *data= (FMod_Generator*)(fcm->data);
|
||||
if (data->coefficients) data->coefficients[0]= value;
|
||||
}
|
||||
|
||||
float FModGenFunc_pre_multiplier_get(PointerRNA *ptr)
|
||||
{
|
||||
FModifier *fcm = (FModifier *)(ptr->data);
|
||||
FMod_Generator *data= (FMod_Generator*)(fcm->data);
|
||||
return (data->coefficients) ? (float)data->coefficients[1] : 1.0f;
|
||||
}
|
||||
|
||||
void FModGenFunc_pre_multiplier_set(PointerRNA *ptr, float value)
|
||||
{
|
||||
FModifier *fcm = (FModifier *)(ptr->data);
|
||||
FMod_Generator *data= (FMod_Generator*)(fcm->data);
|
||||
if (data->coefficients) data->coefficients[1]= value;
|
||||
}
|
||||
|
||||
float FModGenFunc_x_offset_get(PointerRNA *ptr)
|
||||
{
|
||||
FModifier *fcm = (FModifier *)(ptr->data);
|
||||
FMod_Generator *data= (FMod_Generator*)(fcm->data);
|
||||
return (data->coefficients) ? (float)data->coefficients[2] : 0.0f;
|
||||
}
|
||||
|
||||
void FModGenFunc_x_offset_set(PointerRNA *ptr, float value)
|
||||
{
|
||||
FModifier *fcm = (FModifier *)(ptr->data);
|
||||
FMod_Generator *data= (FMod_Generator*)(fcm->data);
|
||||
if (data->coefficients) data->coefficients[2]= value;
|
||||
}
|
||||
|
||||
float FModGenFunc_y_offset_get(PointerRNA *ptr)
|
||||
{
|
||||
FModifier *fcm = (FModifier *)(ptr->data);
|
||||
FMod_Generator *data= (FMod_Generator*)(fcm->data);
|
||||
return (data->coefficients) ? (float)data->coefficients[3] : 0.0f;
|
||||
}
|
||||
|
||||
void FModGenFunc_y_offset_set(PointerRNA *ptr, float value)
|
||||
{
|
||||
FModifier *fcm = (FModifier *)(ptr->data);
|
||||
FMod_Generator *data= (FMod_Generator*)(fcm->data);
|
||||
if (data->coefficients) data->coefficients[3]= value;
|
||||
}
|
||||
|
||||
/* --------- */
|
||||
|
||||
StructRNA *rna_FModifierType_refine(struct PointerRNA *ptr)
|
||||
@@ -111,20 +56,9 @@ StructRNA *rna_FModifierType_refine(struct PointerRNA *ptr)
|
||||
|
||||
switch (fcm->type) {
|
||||
case FMODIFIER_TYPE_GENERATOR:
|
||||
{
|
||||
FMod_Generator *gen= (FMod_Generator *)fcm->data;
|
||||
|
||||
switch (gen->mode) {
|
||||
case FCM_GENERATOR_POLYNOMIAL:
|
||||
return &RNA_FModifierGenerator_PolyExpanded;
|
||||
//case FCM_GENERATOR_POLYNOMIAL_FACTORISED:
|
||||
case FCM_GENERATOR_FUNCTION:
|
||||
return &RNA_FModifierGenerator_Function;
|
||||
//case FCM_GENERATOR_EXPRESSION:
|
||||
default:
|
||||
return &RNA_FModifierGenerator;
|
||||
}
|
||||
}
|
||||
return &RNA_FModifierGenerator;
|
||||
case FMODIFIER_TYPE_FN_GENERATOR:
|
||||
return &RNA_FModifierFunctionGenerator;
|
||||
case FMODIFIER_TYPE_ENVELOPE:
|
||||
return &RNA_FModifierEnvelope;
|
||||
case FMODIFIER_TYPE_CYCLES:
|
||||
@@ -215,21 +149,22 @@ static void rna_FCurve_RnaPath_set(PointerRNA *ptr, const char *value)
|
||||
|
||||
#else
|
||||
|
||||
static void rna_def_fmodifier_generator_common(StructRNA *srna)
|
||||
|
||||
static void rna_def_fmodifier_generator(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
static EnumPropertyItem prop_mode_items[] = {
|
||||
{FCM_GENERATOR_POLYNOMIAL, "POLYNOMIAL", 0, "Expanded Polynomial", ""},
|
||||
{FCM_GENERATOR_POLYNOMIAL_FACTORISED, "POLYNOMIAL_FACTORISED", 0, "Factorised Polynomial", ""},
|
||||
{FCM_GENERATOR_FUNCTION, "FUNCTION", 0, "Built-In Function", ""},
|
||||
{FCM_GENERATOR_EXPRESSION, "EXPRESSION", 0, "Expression", ""},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
/* struct wrapping settings */
|
||||
RNA_def_struct_sdna_from(srna, "FMod_Generator", "data");
|
||||
|
||||
/* settings */
|
||||
srna= RNA_def_struct(brna, "FModifierGenerator", "FModifier");
|
||||
RNA_def_struct_ui_text(srna, "Generator F-Curve Modifier", "Deterministically generates values for the modified F-Curve.");
|
||||
RNA_def_struct_sdna_from(srna, "FMod_Generator", "data");
|
||||
|
||||
/* define common props */
|
||||
prop= RNA_def_property(srna, "additive", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", FCM_GENERATOR_ADDITIVE);
|
||||
RNA_def_property_ui_text(prop, "Additive", "Values generated by this modifier are applied on top of the existing values instead of overwriting them.");
|
||||
@@ -238,42 +173,23 @@ static void rna_def_fmodifier_generator_common(StructRNA *srna)
|
||||
prop= RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_items(prop, prop_mode_items);
|
||||
RNA_def_property_ui_text(prop, "Mode", "Type of generator to use.");
|
||||
}
|
||||
|
||||
/* this is a temporary dummy generator-modifier wrapping (to be discarded) */
|
||||
static void rna_def_fmodifier_generator(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
|
||||
srna= RNA_def_struct(brna, "FModifierGenerator", "FModifier");
|
||||
RNA_def_struct_ui_text(srna, "Generator F-Curve Modifier", "Deterministically generates values for the modified F-Curve.");
|
||||
|
||||
/* define common props */
|
||||
rna_def_fmodifier_generator_common(srna);
|
||||
}
|
||||
|
||||
static void rna_def_fmodifier_generator_polyexpanded(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
srna= RNA_def_struct(brna, "FModifierGenerator_PolyExpanded", "FModifier");
|
||||
RNA_def_struct_ui_text(srna, "Expanded Polynomial Generator", "Generates values for the modified F-Curve using expanded polynomial expresion.");
|
||||
|
||||
/* define common props */
|
||||
rna_def_fmodifier_generator_common(srna);
|
||||
|
||||
/* order of the polynomial */
|
||||
// XXX this has a special validation func
|
||||
prop= RNA_def_property(srna, "poly_order", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_ui_text(prop, "Polynomial Order", "The highest power of 'x' for this polynomial. (i.e. the number of coefficients - 1)");
|
||||
RNA_def_property_ui_text(prop, "Polynomial Order", "The highest power of 'x' for this polynomial. (number of coefficients - 1)");
|
||||
|
||||
/* coefficients array */
|
||||
//prop= RNA_def_property(srna, "coefficients", PROP_FLOAT, PROP_NONE);
|
||||
//RNA_def_property_ui_text(prop, "Coefficients", "Coefficients for 'x' (starting from lowest power).");
|
||||
// FIXME: this is quite difficult to try to wrap
|
||||
//prop= RNA_def_property(srna, "coefficients", PROP_COLLECTION, PROP_NONE);
|
||||
//RNA_def_property_collection_funcs(prop, "rna_FModifierGenerator_coefficients_begin", "rna_FModifierGenerator_coefficients_next", "rna_FModifierGenerator_coefficients_end", "rna_iterator_array_get", "rna_FModifierGenerator_coefficients_length", 0, 0, 0, 0);
|
||||
//RNA_def_property_ui_text(prop, "Coefficients", "Coefficients for 'x' (starting from lowest power of x^0).");
|
||||
}
|
||||
|
||||
static void rna_def_fmodifier_generator_function(BlenderRNA *brna)
|
||||
/* --------- */
|
||||
|
||||
static void rna_def_fmodifier_function_generator(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
@@ -284,48 +200,95 @@ static void rna_def_fmodifier_generator_function(BlenderRNA *brna)
|
||||
{2, "TAN", 0, "Tangent", ""},
|
||||
{3, "SQRT", 0, "Square Root", ""},
|
||||
{4, "LN", 0, "Natural Logarithm", ""},
|
||||
{5, "SINC", 0, "Normalised Sine", "sin(x) / x"},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
|
||||
srna= RNA_def_struct(brna, "FModifierGenerator_Function", "FModifier");
|
||||
RNA_def_struct_ui_text(srna, "Built-In Function Generator", "Generates values for modified F-Curve using Built-In Function.");
|
||||
|
||||
/* common settings */
|
||||
rna_def_fmodifier_generator_common(srna);
|
||||
|
||||
/* type */
|
||||
prop= RNA_def_property(srna, "func_type", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_items(prop, prop_type_items);
|
||||
RNA_def_property_ui_text(prop, "Type", "Type of Built-In function to use as generator.");
|
||||
srna= RNA_def_struct(brna, "FModifierFunctionGenerator", "FModifier");
|
||||
RNA_def_struct_ui_text(srna, "Built-In Function F-Modifier", "Generates values using a Built-In Function.");
|
||||
RNA_def_struct_sdna_from(srna, "FMod_FunctionGenerator", "data");
|
||||
|
||||
/* coefficients */
|
||||
prop= RNA_def_property(srna, "amplitude", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_funcs(prop, "FModGenFunc_amplitude_get", "FModGenFunc_amplitude_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "Amplitude", "Scale factor for y-values generated by the function.");
|
||||
RNA_def_property_ui_text(prop, "Amplitude", "Scale factor determining the maximum/minimum values.");
|
||||
|
||||
prop= RNA_def_property(srna, "pre_multiplier", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_funcs(prop, "FModGenFunc_pre_multiplier_get", "FModGenFunc_pre_multiplier_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "PreMultiplier", "Scale factor for x-value inputs to function.");
|
||||
prop= RNA_def_property(srna, "phase_multiplier", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_ui_text(prop, "Phase Multiplier", "Scale factor determining the 'speed' of the function.");
|
||||
|
||||
prop= RNA_def_property(srna, "x_offset", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_funcs(prop, "FModGenFunc_x_offset_get", "FModGenFunc_x_offset_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "X Offset", "Offset for x-value inputs to function.");
|
||||
prop= RNA_def_property(srna, "phase_offset", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_ui_text(prop, "Phase Offset", "Constant factor to offset time by for function.");
|
||||
|
||||
prop= RNA_def_property(srna, "y_offset", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_funcs(prop, "FModGenFunc_y_offset_get", "FModGenFunc_y_offset_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "Y Offset", "Offset for y-values generated by the function.");
|
||||
prop= RNA_def_property(srna, "value_offset", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_ui_text(prop, "Value Offset", "Constant factor to offset values by.");
|
||||
|
||||
/* flags */
|
||||
prop= RNA_def_property(srna, "additive", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", FCM_GENERATOR_ADDITIVE);
|
||||
RNA_def_property_ui_text(prop, "Additive", "Values generated by this modifier are applied on top of the existing values instead of overwriting them.");
|
||||
|
||||
prop= RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_items(prop, prop_type_items);
|
||||
RNA_def_property_ui_text(prop, "Type", "Type of built-in function to use.");
|
||||
}
|
||||
|
||||
/* --------- */
|
||||
|
||||
static void rna_def_fmodifier_envelope_ctrl(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
srna= RNA_def_struct(brna, "FModifierEnvelopeControlPoint", NULL);
|
||||
RNA_def_struct_ui_text(srna, "Envelope Control Point", "Control point for envelope F-Modifier.");
|
||||
RNA_def_struct_sdna(srna, "FCM_EnvelopeData");
|
||||
|
||||
/* min/max extents
|
||||
* - for now, these are allowed to go past each other, so that we can have inverted action
|
||||
* - technically, the range is limited by the settings in the envelope-modifier data, not here...
|
||||
*/
|
||||
prop= RNA_def_property(srna, "minimum", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "min");
|
||||
RNA_def_property_ui_text(prop, "Minimum Value", "Lower bound of envelope at this control-point.");
|
||||
|
||||
prop= RNA_def_property(srna, "maximum", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "max");
|
||||
RNA_def_property_ui_text(prop, "Maximum Value", "Upper bound of envelope at this control-point.");
|
||||
|
||||
/* Frame */
|
||||
prop= RNA_def_property(srna, "frame", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "time");
|
||||
RNA_def_property_ui_text(prop, "Frame", "Frame this control-point occurs on.");
|
||||
|
||||
// TODO:
|
||||
// - selection flags (not implemented in UI yet though)
|
||||
}
|
||||
|
||||
static void rna_def_fmodifier_envelope(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
//PropertyRNA *prop;
|
||||
PropertyRNA *prop;
|
||||
|
||||
srna= RNA_def_struct(brna, "FModifierEnvelope", "FModifier");
|
||||
RNA_def_struct_ui_text(srna, "Envelope F-Curve Modifier", "Scales the values of the modified F-Curve.");
|
||||
RNA_def_struct_ui_text(srna, "Envelope F-Modifier", "Scales the values of the modified F-Curve.");
|
||||
RNA_def_struct_sdna_from(srna, "FMod_Envelope", "data");
|
||||
|
||||
/* Collections */
|
||||
prop= RNA_def_property(srna, "control_points", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_collection_sdna(prop, NULL, "data", "totvert");
|
||||
RNA_def_property_struct_type(prop, "FModifierEnvelopeControlPoint");
|
||||
RNA_def_property_ui_text(prop, "Control Points", "Control points defining the shape of the envelope.");
|
||||
|
||||
/* Range Settings */
|
||||
prop= RNA_def_property(srna, "reference_value", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "midval");
|
||||
RNA_def_property_ui_text(prop, "Reference Value", "Value that envelope's influence is centered around / based on.");
|
||||
|
||||
prop= RNA_def_property(srna, "default_minimum", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "min");
|
||||
RNA_def_property_ui_text(prop, "Default Minimum", "Lower distance from Reference Value for 1:1 default influence.");
|
||||
|
||||
prop= RNA_def_property(srna, "default_maximum", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "max");
|
||||
RNA_def_property_ui_text(prop, "Default Maximum", "Upper distance from Reference Value for 1:1 default influence.");
|
||||
}
|
||||
|
||||
/* --------- */
|
||||
@@ -343,7 +306,7 @@ static void rna_def_fmodifier_cycles(BlenderRNA *brna)
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
srna= RNA_def_struct(brna, "FModifierCycles", "FModifier");
|
||||
RNA_def_struct_ui_text(srna, "Cycles F-Curve Modifier", "Repeats the values of the modified F-Curve.");
|
||||
RNA_def_struct_ui_text(srna, "Cycles F-Modifier", "Repeats the values of the modified F-Curve.");
|
||||
RNA_def_struct_sdna_from(srna, "FMod_Cycles", "data");
|
||||
|
||||
/* before */
|
||||
@@ -372,7 +335,7 @@ static void rna_def_fmodifier_python(BlenderRNA *brna)
|
||||
//PropertyRNA *prop;
|
||||
|
||||
srna= RNA_def_struct(brna, "FModifierPython", "FModifier");
|
||||
RNA_def_struct_ui_text(srna, "Python F-Curve Modifier", "Performs user-defined operation on the modified F-Curve.");
|
||||
RNA_def_struct_ui_text(srna, "Python F-Modifier", "Performs user-defined operation on the modified F-Curve.");
|
||||
RNA_def_struct_sdna_from(srna, "FMod_Python", "data");
|
||||
}
|
||||
|
||||
@@ -384,7 +347,7 @@ static void rna_def_fmodifier_limits(BlenderRNA *brna)
|
||||
PropertyRNA *prop;
|
||||
|
||||
srna= RNA_def_struct(brna, "FModifierLimits", "FModifier");
|
||||
RNA_def_struct_ui_text(srna, "Limits F-Curve Modifier", "Limits the time/value ranges of the modified F-Curve.");
|
||||
RNA_def_struct_ui_text(srna, "Limits F-Modifier", "Limits the time/value ranges of the modified F-Curve.");
|
||||
RNA_def_struct_sdna_from(srna, "FMod_Limits", "data");
|
||||
|
||||
prop= RNA_def_property(srna, "use_minimum_x", PROP_BOOLEAN, PROP_NONE);
|
||||
@@ -435,7 +398,7 @@ static void rna_def_fmodifier_noise(BlenderRNA *brna)
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
srna= RNA_def_struct(brna, "FModifierNoise", "FModifier");
|
||||
RNA_def_struct_ui_text(srna, "Noise F-Curve Modifier", "Gives randomness to the modified F-Curve.");
|
||||
RNA_def_struct_ui_text(srna, "Noise F-Modifier", "Gives randomness to the modified F-Curve.");
|
||||
RNA_def_struct_sdna_from(srna, "FMod_Noise", "data");
|
||||
|
||||
prop= RNA_def_property(srna, "modification", PROP_ENUM, PROP_NONE);
|
||||
@@ -471,7 +434,7 @@ void rna_def_fmodifier(BlenderRNA *brna)
|
||||
/* base struct definition */
|
||||
srna= RNA_def_struct(brna, "FModifier", NULL);
|
||||
RNA_def_struct_refine_func(srna, "rna_FModifierType_refine");
|
||||
RNA_def_struct_ui_text(srna, "FCurve Modifier", "Modifier for values of F-Curve.");
|
||||
RNA_def_struct_ui_text(srna, "F-Modifier", "Modifier for values of F-Curve.");
|
||||
|
||||
#if 0 // XXX not used yet
|
||||
/* name */
|
||||
@@ -569,6 +532,27 @@ void rna_def_channeldriver(BlenderRNA *brna)
|
||||
|
||||
/* *********************** */
|
||||
|
||||
static void rna_def_fpoint(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
srna= RNA_def_struct(brna, "FCurveSample", NULL);
|
||||
RNA_def_struct_sdna(srna, "FPoint");
|
||||
RNA_def_struct_ui_text(srna, "F-Curve Sample", "Sample point for F-Curve.");
|
||||
|
||||
/* Boolean values */
|
||||
prop= RNA_def_property(srna, "selected", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", 1);
|
||||
RNA_def_property_ui_text(prop, "Selected", "Selection status");
|
||||
|
||||
/* Vector value */
|
||||
prop= RNA_def_property(srna, "point", PROP_FLOAT, PROP_VECTOR);
|
||||
RNA_def_property_array(prop, 2);
|
||||
RNA_def_property_float_sdna(prop, NULL, "vec");
|
||||
RNA_def_property_ui_text(prop, "Point", "Point coordinates");
|
||||
}
|
||||
|
||||
void rna_def_fcurve(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
@@ -619,7 +603,7 @@ void rna_def_fcurve(BlenderRNA *brna)
|
||||
/* Collections */
|
||||
prop= RNA_def_property(srna, "sampled_points", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_collection_sdna(prop, NULL, "fpt", "totvert");
|
||||
RNA_def_property_struct_type(prop, "CurvePoint"); // XXX FPoints not BPoints here! FPoints are much smaller!
|
||||
RNA_def_property_struct_type(prop, "FCurveSample");
|
||||
RNA_def_property_ui_text(prop, "Sampled Points", "Sampled animation data");
|
||||
|
||||
prop= RNA_def_property(srna, "keyframe_points", PROP_COLLECTION, PROP_NONE);
|
||||
@@ -637,6 +621,7 @@ void rna_def_fcurve(BlenderRNA *brna)
|
||||
void RNA_def_fcurve(BlenderRNA *brna)
|
||||
{
|
||||
rna_def_fcurve(brna);
|
||||
rna_def_fpoint(brna);
|
||||
|
||||
rna_def_drivertarget(brna);
|
||||
rna_def_channeldriver(brna);
|
||||
@@ -644,9 +629,9 @@ void RNA_def_fcurve(BlenderRNA *brna)
|
||||
rna_def_fmodifier(brna);
|
||||
|
||||
rna_def_fmodifier_generator(brna);
|
||||
rna_def_fmodifier_generator_polyexpanded(brna);
|
||||
rna_def_fmodifier_generator_function(brna);
|
||||
rna_def_fmodifier_function_generator(brna);
|
||||
rna_def_fmodifier_envelope(brna);
|
||||
rna_def_fmodifier_envelope_ctrl(brna);
|
||||
rna_def_fmodifier_cycles(brna);
|
||||
rna_def_fmodifier_python(brna);
|
||||
rna_def_fmodifier_limits(brna);
|
||||
|
||||
@@ -139,6 +139,7 @@ void RNA_def_material(struct BlenderRNA *brna);
|
||||
void RNA_def_mesh(struct BlenderRNA *brna);
|
||||
void RNA_def_meta(struct BlenderRNA *brna);
|
||||
void RNA_def_modifier(struct BlenderRNA *brna);
|
||||
void RNA_def_nla(struct BlenderRNA *brna);
|
||||
void RNA_def_nodetree(struct BlenderRNA *brna);
|
||||
void RNA_def_object(struct BlenderRNA *brna);
|
||||
void RNA_def_object_force(struct BlenderRNA *brna);
|
||||
|
||||
@@ -506,7 +506,7 @@ static void rna_def_modifier_build(BlenderRNA *brna)
|
||||
RNA_def_struct_ui_icon(srna, ICON_MOD_BUILD);
|
||||
|
||||
prop= RNA_def_property(srna, "start", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_range(prop, 1, MAXFRAMEF);
|
||||
RNA_def_property_range(prop, MINAFRAMEF, MAXFRAMEF);
|
||||
RNA_def_property_ui_text(prop, "Start", "Specify the start frame of the effect.");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Modifier_update");
|
||||
|
||||
@@ -660,18 +660,18 @@ static void rna_def_modifier_wave(BlenderRNA *brna)
|
||||
|
||||
prop= RNA_def_property(srna, "time_offset", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "timeoffs");
|
||||
RNA_def_property_range(prop, -MAXFRAMEF, MAXFRAMEF);
|
||||
RNA_def_property_range(prop, MINAFRAMEF, MAXFRAMEF);
|
||||
RNA_def_property_ui_text(prop, "Time Offset", "Either the starting frame (for positive speed) or ending frame (for negative speed.)");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Modifier_update");
|
||||
|
||||
prop= RNA_def_property(srna, "lifetime", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_range(prop, -MAXFRAMEF, MAXFRAMEF);
|
||||
RNA_def_property_range(prop, MINAFRAMEF, MAXFRAMEF);
|
||||
RNA_def_property_ui_text(prop, "Lifetime", "");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Modifier_update");
|
||||
|
||||
prop= RNA_def_property(srna, "damping_time", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "damp");
|
||||
RNA_def_property_range(prop, -MAXFRAMEF, MAXFRAMEF);
|
||||
RNA_def_property_range(prop, MINAFRAMEF, MAXFRAMEF);
|
||||
RNA_def_property_ui_text(prop, "Damping Time", "");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Modifier_update");
|
||||
|
||||
|
||||
460
source/blender/makesrna/intern/rna_nla.c
Normal file
460
source/blender/makesrna/intern/rna_nla.c
Normal file
@@ -0,0 +1,460 @@
|
||||
/**
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* Contributor(s): Blender Foundation (2009), Joshua Leung
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "RNA_define.h"
|
||||
#include "RNA_types.h"
|
||||
|
||||
#include "rna_internal.h"
|
||||
|
||||
#include "DNA_anim_types.h"
|
||||
#include "DNA_action_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#ifdef RNA_RUNTIME
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
/* needed for some of the validation stuff... */
|
||||
#include "BKE_animsys.h"
|
||||
#include "BKE_nla.h"
|
||||
|
||||
/* temp constant defined for these funcs only... */
|
||||
#define NLASTRIP_MIN_LEN_THRESH 0.1f
|
||||
|
||||
void rna_NlaStrip_name_set(PointerRNA *ptr, const char *value)
|
||||
{
|
||||
NlaStrip *data= (NlaStrip *)ptr->data;
|
||||
|
||||
/* copy the name first */
|
||||
BLI_strncpy(data->name, value, sizeof(data->name));
|
||||
|
||||
/* validate if there's enough info to do so */
|
||||
if (ptr->id.data) {
|
||||
AnimData *adt= BKE_animdata_from_id(ptr->id.data);
|
||||
BKE_nlastrip_validate_name(adt, data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void rna_NlaStrip_start_frame_set(PointerRNA *ptr, float value)
|
||||
{
|
||||
NlaStrip *data= (NlaStrip*)ptr->data;
|
||||
|
||||
/* clamp value to lie within valid limits
|
||||
* - cannot start past the end of the strip + some flexibility threshold
|
||||
* - cannot start before the previous strip (if present) ends
|
||||
* -> but if it was a transition, we could go up to the start of the strip + some flexibility threshold
|
||||
* as long as we re-adjust the transition afterwards
|
||||
* - minimum frame is -MAXFRAME so that we don't get clipping on frame 0
|
||||
*/
|
||||
if (data->prev) {
|
||||
if (data->prev->type == NLASTRIP_TYPE_TRANSITION) {
|
||||
CLAMP(value, data->prev->start+NLASTRIP_MIN_LEN_THRESH, data->end-NLASTRIP_MIN_LEN_THRESH);
|
||||
|
||||
/* readjust the transition to stick to the endpoints of the action-clips */
|
||||
data->prev->end= value;
|
||||
}
|
||||
else {
|
||||
CLAMP(value, data->prev->end, data->end-NLASTRIP_MIN_LEN_THRESH);
|
||||
}
|
||||
}
|
||||
else {
|
||||
CLAMP(value, MINAFRAME, data->end);
|
||||
}
|
||||
data->start= value;
|
||||
}
|
||||
|
||||
static void rna_NlaStrip_end_frame_set(PointerRNA *ptr, float value)
|
||||
{
|
||||
NlaStrip *data= (NlaStrip*)ptr->data;
|
||||
|
||||
/* clamp value to lie within valid limits
|
||||
* - must not have zero or negative length strip, so cannot start before the first frame
|
||||
* + some minimum-strip-length threshold
|
||||
* - cannot end later than the start of the next strip (if present)
|
||||
* -> but if it was a transition, we could go up to the start of the end - some flexibility threshold
|
||||
* as long as we re-adjust the transition afterwards
|
||||
*/
|
||||
if (data->next) {
|
||||
if (data->next->type == NLASTRIP_TYPE_TRANSITION) {
|
||||
CLAMP(value, data->start+NLASTRIP_MIN_LEN_THRESH, data->next->end-NLASTRIP_MIN_LEN_THRESH);
|
||||
|
||||
/* readjust the transition to stick to the endpoints of the action-clips */
|
||||
data->next->start= value;
|
||||
}
|
||||
else {
|
||||
CLAMP(value, data->start+NLASTRIP_MIN_LEN_THRESH, data->next->start);
|
||||
}
|
||||
}
|
||||
else {
|
||||
CLAMP(value, data->start+NLASTRIP_MIN_LEN_THRESH, MAXFRAME);
|
||||
}
|
||||
data->end= value;
|
||||
|
||||
|
||||
/* calculate the lengths the strip and its action (if applicable) */
|
||||
if (data->type == NLASTRIP_TYPE_CLIP) {
|
||||
float len, actlen;
|
||||
|
||||
len= data->end - data->start;
|
||||
actlen= data->actend - data->actstart;
|
||||
if (IS_EQ(actlen, 0.0f)) actlen= 1.0f;
|
||||
|
||||
/* now, adjust the 'scale' setting to reflect this (so that this change can be valid) */
|
||||
data->scale= len / ((actlen) * data->repeat);
|
||||
}
|
||||
}
|
||||
|
||||
static void rna_NlaStrip_scale_set(PointerRNA *ptr, float value)
|
||||
{
|
||||
NlaStrip *data= (NlaStrip*)ptr->data;
|
||||
float actlen, mapping;
|
||||
|
||||
/* set scale value */
|
||||
CLAMP(value, 0.0001f, 1000.0f); /* NOTE: these need to be synced with the values in the property definition in rna_def_nlastrip() */
|
||||
data->scale= value;
|
||||
|
||||
/* calculate existing factors */
|
||||
actlen= data->actend - data->actstart;
|
||||
if (IS_EQ(actlen, 0.0f)) actlen= 1.0f;
|
||||
mapping= data->scale * data->repeat;
|
||||
|
||||
/* adjust endpoint of strip in response to this */
|
||||
if (IS_EQ(mapping, 0.0f) == 0)
|
||||
data->end = (actlen * mapping) + data->start;
|
||||
else
|
||||
printf("NlaStrip Set Scale Error (in RNA): Scale = %0.4f, Repeat = %0.4f \n", data->scale, data->repeat);
|
||||
}
|
||||
|
||||
static void rna_NlaStrip_repeat_set(PointerRNA *ptr, float value)
|
||||
{
|
||||
NlaStrip *data= (NlaStrip*)ptr->data;
|
||||
float actlen, mapping;
|
||||
|
||||
/* set scale value */
|
||||
CLAMP(value, 0.01f, 1000.0f); /* NOTE: these need to be synced with the values in the property definition in rna_def_nlastrip() */
|
||||
data->repeat= value;
|
||||
|
||||
/* calculate existing factors */
|
||||
actlen= data->actend - data->actstart;
|
||||
if (IS_EQ(actlen, 0.0f)) actlen= 1.0f;
|
||||
mapping= data->scale * data->repeat;
|
||||
|
||||
/* adjust endpoint of strip in response to this */
|
||||
if (IS_EQ(mapping, 0.0f) == 0)
|
||||
data->end = (actlen * mapping) + data->start;
|
||||
else
|
||||
printf("NlaStrip Set Repeat Error (in RNA): Scale = %0.4f, Repeat = %0.4f \n", data->scale, data->repeat);
|
||||
}
|
||||
|
||||
static void rna_NlaStrip_blend_in_set(PointerRNA *ptr, float value)
|
||||
{
|
||||
NlaStrip *data= (NlaStrip*)ptr->data;
|
||||
float len;
|
||||
|
||||
/* blend-in is limited to the length of the strip, and also cannot overlap with blendout */
|
||||
len= (data->end - data->start) - data->blendout;
|
||||
CLAMP(value, 0, len);
|
||||
|
||||
data->blendin= value;
|
||||
}
|
||||
|
||||
static void rna_NlaStrip_blend_out_set(PointerRNA *ptr, float value)
|
||||
{
|
||||
NlaStrip *data= (NlaStrip*)ptr->data;
|
||||
float len;
|
||||
|
||||
/* blend-out is limited to the length of the strip */
|
||||
len= (data->end - data->start);
|
||||
CLAMP(value, 0, len);
|
||||
|
||||
/* it also cannot overlap with blendin */
|
||||
if ((len - value) < data->blendin)
|
||||
value= len - data->blendin;
|
||||
|
||||
data->blendout= value;
|
||||
}
|
||||
|
||||
static void rna_NlaStrip_action_start_frame_set(PointerRNA *ptr, float value)
|
||||
{
|
||||
NlaStrip *data= (NlaStrip*)ptr->data;
|
||||
CLAMP(value, MINAFRAME, data->actend);
|
||||
data->actstart= value;
|
||||
}
|
||||
|
||||
static void rna_NlaStrip_action_end_frame_set(PointerRNA *ptr, float value)
|
||||
{
|
||||
NlaStrip *data= (NlaStrip*)ptr->data;
|
||||
CLAMP(value, data->actstart, MAXFRAME);
|
||||
data->actend= value;
|
||||
}
|
||||
|
||||
static void rna_NlaStrip_animated_influence_set(PointerRNA *ptr, int value)
|
||||
{
|
||||
NlaStrip *data= (NlaStrip*)ptr->data;
|
||||
|
||||
if (value) {
|
||||
/* set the flag, then make sure a curve for this exists */
|
||||
data->flag |= NLASTRIP_FLAG_USR_INFLUENCE;
|
||||
BKE_nlastrip_validate_fcurves(data);
|
||||
}
|
||||
else
|
||||
data->flag &= ~NLASTRIP_FLAG_USR_INFLUENCE;
|
||||
}
|
||||
|
||||
static void rna_NlaStrip_animated_time_set(PointerRNA *ptr, int value)
|
||||
{
|
||||
NlaStrip *data= (NlaStrip*)ptr->data;
|
||||
|
||||
if (value) {
|
||||
/* set the flag, then make sure a curve for this exists */
|
||||
data->flag |= NLASTRIP_FLAG_USR_TIME;
|
||||
BKE_nlastrip_validate_fcurves(data);
|
||||
}
|
||||
else
|
||||
data->flag &= ~NLASTRIP_FLAG_USR_TIME;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void rna_def_nlastrip(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
/* enum defs */
|
||||
static EnumPropertyItem prop_type_items[] = {
|
||||
{NLASTRIP_TYPE_CLIP, "CLIP", 0, "Action Clip", "NLA Strip references some Action."},
|
||||
{NLASTRIP_TYPE_TRANSITION, "TRANSITION", 0, "Transition", "NLA Strip 'transitions' between adjacent strips."},
|
||||
{NLASTRIP_TYPE_META, "META", 0, "Meta", "NLA Strip acts as a container for adjacent strips."},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
static EnumPropertyItem prop_mode_blend_items[] = {
|
||||
{NLASTRIP_MODE_REPLACE, "REPLACE", 0, "Replace", "Result strip replaces the accumulated results by amount specified by influence."},
|
||||
{NLASTRIP_MODE_ADD, "ADD", 0, "Add", "Weighted result of strip is added to the accumlated results."},
|
||||
{NLASTRIP_MODE_SUBTRACT, "SUBTRACT", 0, "Subtract", "Weighted result of strip is removed from the accumlated results."},
|
||||
{NLASTRIP_MODE_MULTIPLY, "MULITPLY", 0, "Multiply", "Weighted result of strip is multiplied with the accumlated results."},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
static EnumPropertyItem prop_mode_extend_items[] = {
|
||||
{NLASTRIP_EXTEND_NOTHING, "NOTHING", 0, "Nothing", "Strip has no influence past its extents."},
|
||||
{NLASTRIP_EXTEND_HOLD, "HOLD", 0, "Hold", "Hold the first frame if no previous strips in track, and always hold last frame."},
|
||||
{NLASTRIP_EXTEND_HOLD_FORWARD, "HOLD_FORWARD", 0, "Hold Forward", "Only hold last frame."},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
/* struct definition */
|
||||
srna= RNA_def_struct(brna, "NlaStrip", NULL);
|
||||
RNA_def_struct_ui_text(srna, "NLA Strip", "A container referencing an existing Action.");
|
||||
RNA_def_struct_ui_icon(srna, ICON_NLA); // XXX
|
||||
|
||||
/* name property */
|
||||
prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_ui_text(prop, "Name", "");
|
||||
RNA_def_property_string_funcs(prop, NULL, NULL, "rna_NlaStrip_name_set");
|
||||
RNA_def_struct_name_property(srna, prop);
|
||||
|
||||
/* Enums */
|
||||
prop= RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "type");
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE); // XXX for now, not editable, since this is dangerous
|
||||
RNA_def_property_enum_items(prop, prop_type_items);
|
||||
RNA_def_property_ui_text(prop, "Type", "Type of NLA Strip.");
|
||||
|
||||
prop= RNA_def_property(srna, "extrapolation", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "extendmode");
|
||||
RNA_def_property_enum_items(prop, prop_mode_extend_items);
|
||||
RNA_def_property_ui_text(prop, "Extrapolation", "Action to take for gaps past the strip extents.");
|
||||
|
||||
prop= RNA_def_property(srna, "blending", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "blendmode");
|
||||
RNA_def_property_enum_items(prop, prop_mode_blend_items);
|
||||
RNA_def_property_ui_text(prop, "Blending", "Method used for combining strip's result with accumulated result.");
|
||||
|
||||
/* Strip extents */
|
||||
prop= RNA_def_property(srna, "start_frame", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "start");
|
||||
RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_start_frame_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "Start Frame", "");
|
||||
|
||||
prop= RNA_def_property(srna, "end_frame", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "end");
|
||||
RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_end_frame_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "End Frame", "");
|
||||
|
||||
/* Blending */
|
||||
prop= RNA_def_property(srna, "blend_in", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "blendin");
|
||||
RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_blend_in_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "Blend In", "Number of frames at start of strip to fade in influence.");
|
||||
|
||||
prop= RNA_def_property(srna, "blend_out", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "blendout");
|
||||
RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_blend_out_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "Blend Out", "");
|
||||
|
||||
prop= RNA_def_property(srna, "auto_blending", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_AUTO_BLENDS);
|
||||
RNA_def_property_ui_text(prop, "Auto Blend In/Out", "Number of frames for Blending In/Out is automatically determined from overlapping strips.");
|
||||
|
||||
/* Action */
|
||||
prop= RNA_def_property(srna, "action", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_pointer_sdna(prop, NULL, "act");
|
||||
RNA_def_property_ui_text(prop, "Action", "Action referenced by this strip.");
|
||||
|
||||
/* Action extents */
|
||||
prop= RNA_def_property(srna, "action_start_frame", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "actstart");
|
||||
RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_action_start_frame_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "Action Start Frame", "");
|
||||
|
||||
prop= RNA_def_property(srna, "action_end_frame", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "actend");
|
||||
RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_action_end_frame_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "Action End Frame", "");
|
||||
|
||||
/* Action Reuse */
|
||||
prop= RNA_def_property(srna, "repeat", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "repeat");
|
||||
RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_repeat_set", NULL);
|
||||
RNA_def_property_range(prop, 0.1f, 1000.0f); /* these limits have currently be chosen arbitarily, but could be extended (minimum should still be > 0 though) if needed... */
|
||||
RNA_def_property_ui_text(prop, "Repeat", "Number of times to repeat the action range.");
|
||||
|
||||
prop= RNA_def_property(srna, "scale", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "scale");
|
||||
RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_scale_set", NULL);
|
||||
RNA_def_property_range(prop, 0.0001f, 1000.0f); /* these limits can be extended, but beyond this, we can get some crazy+annoying bugs due to numeric errors */
|
||||
RNA_def_property_ui_text(prop, "Scale", "Scaling factor for action.");
|
||||
|
||||
/* Strip's F-Curves */
|
||||
prop= RNA_def_property(srna, "fcurves", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "FCurve");
|
||||
RNA_def_property_ui_text(prop, "F-Curves", "F-Curves for controlling the strip's influence and timing.");
|
||||
|
||||
/* Strip's F-Modifiers */
|
||||
prop= RNA_def_property(srna, "modifiers", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "FModifier");
|
||||
RNA_def_property_ui_text(prop, "Modifiers", "Modifiers affecting all the F-Curves in the referenced Action.");
|
||||
|
||||
/* Strip's Sub-Strips (for Meta-Strips) */
|
||||
prop= RNA_def_property(srna, "strips", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "NlaStrip");
|
||||
RNA_def_property_ui_text(prop, "NLA Strips", "NLA Strips that this strip acts as a container for (if it is of type Meta).");
|
||||
|
||||
/* Settings - Values necessary for evaluation */
|
||||
prop= RNA_def_property(srna, "influence", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_range(prop, 0.0f, 1.0f);
|
||||
RNA_def_property_ui_text(prop, "Influence", "Amount the strip contributes to the current result.");
|
||||
|
||||
prop= RNA_def_property(srna, "strip_time", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_ui_text(prop, "Strip Time", "Frame of referenced Action to evaluate.");
|
||||
|
||||
// TODO: should the animated_influence/time settings be animatable themselves?
|
||||
prop= RNA_def_property(srna, "animated_influence", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_USR_INFLUENCE);
|
||||
RNA_def_property_boolean_funcs(prop, NULL, "rna_NlaStrip_animated_influence_set");
|
||||
RNA_def_property_ui_text(prop, "Animated Influence", "Influence setting is controlled by an F-Curve rather than automatically determined.");
|
||||
|
||||
prop= RNA_def_property(srna, "animated_time", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_USR_TIME);
|
||||
RNA_def_property_boolean_funcs(prop, NULL, "rna_NlaStrip_animated_time_set");
|
||||
RNA_def_property_ui_text(prop, "Animated Strip Time", "Strip time is controlled by an F-Curve rather than automatically determined.");
|
||||
|
||||
/* settings */
|
||||
prop= RNA_def_property(srna, "active", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* can be made editable by hooking it up to the necessary NLA API methods */
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_ACTIVE);
|
||||
RNA_def_property_ui_text(prop, "Active", "NLA Strip is active.");
|
||||
|
||||
prop= RNA_def_property(srna, "selected", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_SELECT);
|
||||
RNA_def_property_ui_text(prop, "Selected", "NLA Strip is selected.");
|
||||
|
||||
prop= RNA_def_property(srna, "muted", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_MUTED);
|
||||
RNA_def_property_ui_text(prop, "Muted", "NLA Strip is not evaluated.");
|
||||
|
||||
prop= RNA_def_property(srna, "reversed", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_REVERSE);
|
||||
RNA_def_property_ui_text(prop, "Reversed", "NLA Strip is played back in reverse order (only when timing is automatically determined).");
|
||||
|
||||
// TODO:
|
||||
// - sync length
|
||||
}
|
||||
|
||||
void rna_def_nlatrack(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
srna= RNA_def_struct(brna, "NlaTrack", NULL);
|
||||
RNA_def_struct_ui_text(srna, "NLA Track", "A animation layer containing Actions referenced as NLA strips.");
|
||||
RNA_def_struct_ui_icon(srna, ICON_NLA);
|
||||
|
||||
/* strips collection */
|
||||
prop= RNA_def_property(srna, "strips", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "NlaStrip");
|
||||
RNA_def_property_ui_text(prop, "NLA Strips", "NLA Strips on this NLA-track.");
|
||||
|
||||
/* name property */
|
||||
prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_ui_text(prop, "Name", "");
|
||||
RNA_def_struct_name_property(srna, prop);
|
||||
|
||||
/* settings */
|
||||
prop= RNA_def_property(srna, "active", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* can be made editable by hooking it up to the necessary NLA API methods */
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", NLATRACK_ACTIVE);
|
||||
RNA_def_property_ui_text(prop, "Active", "NLA Track is active.");
|
||||
|
||||
prop= RNA_def_property(srna, "solo", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* can be made editable by hooking it up to the necessary NLA API methods */
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", NLATRACK_SOLO);
|
||||
RNA_def_property_ui_text(prop, "Solo", "NLA Track is evaluated itself (i.e. active Action and all other NLA Tracks in the same AnimData block are disabled).");
|
||||
|
||||
prop= RNA_def_property(srna, "selected", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", NLATRACK_SELECTED);
|
||||
RNA_def_property_ui_text(prop, "Selected", "NLA Track is selected.");
|
||||
|
||||
prop= RNA_def_property(srna, "muted", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", NLATRACK_MUTED);
|
||||
RNA_def_property_ui_text(prop, "Muted", "NLA Track is not evaluated.");
|
||||
|
||||
prop= RNA_def_property(srna, "locked", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", NLATRACK_PROTECTED);
|
||||
RNA_def_property_ui_text(prop, "Locked", "NLA Track is locked.");
|
||||
}
|
||||
|
||||
/* --------- */
|
||||
|
||||
void RNA_def_nla(BlenderRNA *brna)
|
||||
{
|
||||
rna_def_nlatrack(brna);
|
||||
rna_def_nlastrip(brna);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1170,7 +1170,7 @@ static void rna_def_object(BlenderRNA *brna)
|
||||
|
||||
prop= RNA_def_property(srna, "time_offset", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "sf");
|
||||
RNA_def_property_range(prop, -MAXFRAMEF, MAXFRAMEF);
|
||||
RNA_def_property_range(prop, MINAFRAMEF, MAXFRAMEF);
|
||||
RNA_def_property_ui_text(prop, "Time Offset", "Animation offset in frames for IPO's and dupligroup instances.");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_TRANSFORM, "rna_Object_update");
|
||||
|
||||
@@ -1264,29 +1264,6 @@ static void rna_def_object(BlenderRNA *brna)
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Pose Mode", "Object with armature data is in pose mode.");
|
||||
|
||||
// XXX this stuff should be moved to AnimData...
|
||||
/*
|
||||
prop= RNA_def_property(srna, "nla_disable_path", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "nlaflag", OB_DISABLE_PATH);
|
||||
RNA_def_property_ui_text(prop, "NLA Disable Path", "Disable path temporally, for editing cycles.");
|
||||
|
||||
prop= RNA_def_property(srna, "nla_collapsed", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "nlaflag", OB_NLA_COLLAPSED);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "NLA Collapsed", "");
|
||||
|
||||
prop= RNA_def_property(srna, "nla_override", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "nlaflag", OB_NLA_OVERRIDE);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "NLA Override", "");
|
||||
|
||||
prop= RNA_def_property(srna, "nla_strips", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_collection_sdna(prop, NULL, "nlastrips", NULL);
|
||||
RNA_def_property_struct_type(prop, "UnknownType");
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "NLA Strips", "NLA strips of the object.");
|
||||
*/
|
||||
|
||||
/* shape keys */
|
||||
|
||||
prop= RNA_def_property(srna, "shape_key_lock", PROP_BOOLEAN, PROP_NONE);
|
||||
|
||||
@@ -226,8 +226,8 @@ static void rna_PartSettings_start_set(struct PointerRNA *ptr, float value)
|
||||
|
||||
if(settings->type==PART_REACTOR && value < 1.0)
|
||||
value = 1.0;
|
||||
else if (value < -30000.0f) //TODO: replace 30000 with MAXFRAMEF when available in 2.5
|
||||
value = -30000.0f;
|
||||
else if (value < MINAFRAMEF)
|
||||
value = MINAFRAMEF;
|
||||
|
||||
settings->sta = value;
|
||||
}
|
||||
@@ -1090,19 +1090,19 @@ static void rna_def_particle_settings(BlenderRNA *brna)
|
||||
/* general values */
|
||||
prop= RNA_def_property(srna, "start", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "sta");//optional if prop names are the same
|
||||
RNA_def_property_range(prop, -30000.0f, 30000.0f); //TODO: replace 30000 with MAXFRAMEF when available in 2.5
|
||||
RNA_def_property_range(prop, MINAFRAMEF, MAXFRAMEF);
|
||||
RNA_def_property_float_funcs(prop, NULL, "rna_PartSettings_start_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "Start", "Frame # to start emitting particles.");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
|
||||
|
||||
prop= RNA_def_property(srna, "end", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_range(prop, -30000.0f, 30000.0f); //TODO: replace 30000 with MAXFRAMEF when available in 2.5
|
||||
RNA_def_property_range(prop, MINAFRAMEF, MAXFRAMEF);
|
||||
RNA_def_property_float_funcs(prop, NULL, "rna_PartSettings_end_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "End", "Frame # to stop emitting particles.");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
|
||||
|
||||
prop= RNA_def_property(srna, "lifetime", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_range(prop, 1.0f, 30000.0f);
|
||||
RNA_def_property_range(prop, 1.0f, MAXFRAMEF);
|
||||
RNA_def_property_ui_text(prop, "Lifetime", "Specify the life span of the particles");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
|
||||
|
||||
|
||||
@@ -975,7 +975,7 @@ void RNA_def_scene(BlenderRNA *brna)
|
||||
prop= RNA_def_property(srna, "current_frame", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATEABLE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "r.cfra");
|
||||
RNA_def_property_range(prop, MINFRAME, MAXFRAME);
|
||||
RNA_def_property_range(prop, MINAFRAME, MAXFRAME);
|
||||
RNA_def_property_ui_text(prop, "Current Frame", "");
|
||||
RNA_def_property_update(prop, NC_SCENE|ND_FRAME, "rna_Scene_frame_update");
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
#include "rna_internal.h"
|
||||
|
||||
#include "DNA_action_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
#include "DNA_view3d_types.h"
|
||||
@@ -89,9 +90,8 @@ static StructRNA* rna_Space_refine(struct PointerRNA *ptr)
|
||||
switch(space->spacetype) {
|
||||
case SPACE_VIEW3D:
|
||||
return &RNA_Space3DView;
|
||||
/*case SPACE_IPO:
|
||||
case SPACE_IPO:
|
||||
return &RNA_SpaceGraphEditor;
|
||||
*/
|
||||
case SPACE_OUTLINER:
|
||||
return &RNA_SpaceOutliner;
|
||||
case SPACE_BUTS:
|
||||
@@ -109,12 +109,12 @@ static StructRNA* rna_Space_refine(struct PointerRNA *ptr)
|
||||
//case SPACE_IMASEL:
|
||||
// return &RNA_SpaceImageBrowser;
|
||||
/*case SPACE_SOUND:
|
||||
return &RNA_SpaceAudioWindow;
|
||||
return &RNA_SpaceAudioWindow;*/
|
||||
case SPACE_ACTION:
|
||||
return &RNA_SpaceDopeSheetEditor;
|
||||
case SPACE_NLA:
|
||||
return &RNA_SpaceNLAEditor;
|
||||
case SPACE_SCRIPT:
|
||||
return &RNA_SpaceNLA;
|
||||
/*case SPACE_SCRIPT:
|
||||
return &RNA_SpaceScriptsWindow;
|
||||
case SPACE_TIME:
|
||||
return &RNA_SpaceTimeline;
|
||||
@@ -872,6 +872,117 @@ static void rna_def_space_text(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Replace Text", "Text to replace selected text with using the replace tool.");
|
||||
}
|
||||
|
||||
static void rna_def_space_dopesheet(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
static EnumPropertyItem mode_items[] = {
|
||||
{SACTCONT_DOPESHEET, "DOPESHEET", 0, "DopeSheet", ""},
|
||||
{SACTCONT_ACTION, "ACTION", 0, "Action Editor", ""},
|
||||
{SACTCONT_SHAPEKEY, "SHAPEKEY", 0, "ShapeKey Editor", ""}, // XXX to be depreceated?
|
||||
{SACTCONT_GPENCIL, "GPENCIL", 0, "Grease Pencil", ""},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
|
||||
srna= RNA_def_struct(brna, "SpaceDopeSheetEditor", "Space");
|
||||
RNA_def_struct_sdna(srna, "SpaceAction");
|
||||
RNA_def_struct_ui_text(srna, "Space DopeSheet Editor", "DopeSheet space data.");
|
||||
|
||||
/* mode */
|
||||
prop= RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "mode");
|
||||
RNA_def_property_enum_items(prop, mode_items);
|
||||
RNA_def_property_ui_text(prop, "Mode", "Editing context being displayed.");
|
||||
|
||||
/* display */
|
||||
prop= RNA_def_property(srna, "show_seconds", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", SACTION_DRAWTIME);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE); // XXX for now, only set with operator
|
||||
RNA_def_property_ui_text(prop, "Show Seconds", "Show timing in seconds not frames.");
|
||||
|
||||
prop= RNA_def_property(srna, "show_cframe_indicator", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SACTION_NODRAWCFRANUM);
|
||||
RNA_def_property_ui_text(prop, "Show Frame Number Indicator", "Show frame number beside the current frame indicator line.");
|
||||
|
||||
prop= RNA_def_property(srna, "show_sliders", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", SACTION_SLIDERS);
|
||||
RNA_def_property_ui_text(prop, "Show Sliders", "Show sliders beside F-Curve channels.");
|
||||
|
||||
/* editing */
|
||||
prop= RNA_def_property(srna, "automerge_keyframes", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SACTION_NOTRANSKEYCULL);
|
||||
RNA_def_property_ui_text(prop, "AutoMerge Keyframes", "Show handles of Bezier control points.");
|
||||
|
||||
// TODO... autosnap, dopesheet?
|
||||
}
|
||||
|
||||
static void rna_def_space_graph(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
static EnumPropertyItem mode_items[] = {
|
||||
{SIPO_MODE_ANIMATION, "FCURVES", 0, "F-Curves", ""},
|
||||
{SIPO_MODE_DRIVERS, "DRIVERS", 0, "Drivers", ""},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
|
||||
srna= RNA_def_struct(brna, "SpaceGraphEditor", "Space");
|
||||
RNA_def_struct_sdna(srna, "SpaceIpo");
|
||||
RNA_def_struct_ui_text(srna, "Space Graph Editor", "Graph Editor space data.");
|
||||
|
||||
/* mode */
|
||||
prop= RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "mode");
|
||||
RNA_def_property_enum_items(prop, mode_items);
|
||||
RNA_def_property_ui_text(prop, "Mode", "Editing context being displayed.");
|
||||
|
||||
/* display */
|
||||
prop= RNA_def_property(srna, "show_seconds", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", SIPO_DRAWTIME);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE); // XXX for now, only set with operator
|
||||
RNA_def_property_ui_text(prop, "Show Seconds", "Show timing in seconds not frames.");
|
||||
|
||||
prop= RNA_def_property(srna, "show_cframe_indicator", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SIPO_NODRAWCFRANUM);
|
||||
RNA_def_property_ui_text(prop, "Show Frame Number Indicator", "Show frame number beside the current frame indicator line.");
|
||||
|
||||
prop= RNA_def_property(srna, "show_handles", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", SIPO_NOHANDLES);
|
||||
RNA_def_property_ui_text(prop, "Show Handles", "Show handles of Bezier control points.");
|
||||
|
||||
/* editing */
|
||||
prop= RNA_def_property(srna, "automerge_keyframes", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SIPO_NOTRANSKEYCULL);
|
||||
RNA_def_property_ui_text(prop, "AutoMerge Keyframes", "Show handles of Bezier control points.");
|
||||
|
||||
// TODO... autosnap, dopesheet?
|
||||
}
|
||||
|
||||
static void rna_def_space_nla(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
srna= RNA_def_struct(brna, "SpaceNLA", "Space");
|
||||
RNA_def_struct_sdna(srna, "SpaceNla");
|
||||
RNA_def_struct_ui_text(srna, "Space Nla Editor", "NLA editor space data.");
|
||||
|
||||
/* display */
|
||||
prop= RNA_def_property(srna, "show_seconds", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", SNLA_DRAWTIME);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE); // XXX for now, only set with operator
|
||||
RNA_def_property_ui_text(prop, "Show Seconds", "Show timing in seconds not frames.");
|
||||
|
||||
prop= RNA_def_property(srna, "show_cframe_indicator", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SNLA_NODRAWCFRANUM);
|
||||
RNA_def_property_ui_text(prop, "Show Frame Number Indicator", "Show frame number beside the current frame indicator line.");
|
||||
|
||||
/* editing */
|
||||
// TODO... autosnap, dopesheet?
|
||||
}
|
||||
|
||||
static void rna_def_fileselect_params(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
@@ -1009,6 +1120,9 @@ void RNA_def_space(BlenderRNA *brna)
|
||||
rna_def_background_image(brna);
|
||||
rna_def_space_3dview(brna);
|
||||
rna_def_space_buttons(brna);
|
||||
rna_def_space_dopesheet(brna);
|
||||
rna_def_space_graph(brna);
|
||||
rna_def_space_nla(brna);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -129,6 +129,7 @@ typedef struct wmNotifier {
|
||||
#define NC_TEXT (12<<24)
|
||||
#define NC_WORLD (13<<24)
|
||||
#define NC_FILE (14<<24)
|
||||
#define NC_ANIMATION (15<<24)
|
||||
|
||||
/* data type, 256 entries is enough, it can overlap */
|
||||
#define NOTE_DATA 0x00FF0000
|
||||
@@ -188,6 +189,16 @@ typedef struct wmNotifier {
|
||||
#define ND_PARAMS (60<<16)
|
||||
#define ND_FILELIST (61<<16)
|
||||
|
||||
/* NC_ANIMATION Animato */
|
||||
#define ND_KEYFRAME_SELECT (70<<16)
|
||||
#define ND_KEYFRAME_EDIT (71<<16)
|
||||
#define ND_KEYFRAME_PROP (72<<16)
|
||||
#define ND_ANIMCHAN_SELECT (73<<16)
|
||||
#define ND_ANIMCHAN_EDIT (74<<16)
|
||||
#define ND_NLA_SELECT (75<<16)
|
||||
#define ND_NLA_EDIT (76<<16)
|
||||
#define ND_NLA_ACTCHANGE (77<<16)
|
||||
|
||||
/* subtype, 256 entries too */
|
||||
#define NOTE_SUBTYPE 0x0000FF00
|
||||
|
||||
|
||||
Reference in New Issue
Block a user