diff options
author | Joseph Eagar <joeedh@gmail.com> | 2011-02-27 09:19:40 +0300 |
---|---|---|
committer | Joseph Eagar <joeedh@gmail.com> | 2011-02-27 09:19:40 +0300 |
commit | f01261d040be27337db9f9996d648a279c89b7c4 (patch) | |
tree | c448230939b3c90d53ce8852dd00925d6052e3a4 /source/blender/editors/animation | |
parent | dcaeda5c4e3a0687251b8511de4f2e8b85ef75c0 (diff) | |
parent | 2198cfdb2deec8b2e85e242c74a032f43d0b26ca (diff) |
merge with/from trunk at r35190
Diffstat (limited to 'source/blender/editors/animation')
19 files changed, 2334 insertions, 1237 deletions
diff --git a/source/blender/editors/animation/CMakeLists.txt b/source/blender/editors/animation/CMakeLists.txt index d5eef6bbd34..f506d278cae 100644 --- a/source/blender/editors/animation/CMakeLists.txt +++ b/source/blender/editors/animation/CMakeLists.txt @@ -19,11 +19,10 @@ # # ***** END GPL LICENSE BLOCK ***** -FILE(GLOB SRC *.c) - -SET(INC +set(INC ../include ../../blenkernel + ../../blenloader ../../blenlib ../../makesdna ../../makesrna @@ -31,4 +30,24 @@ SET(INC ../../../../intern/guardedalloc ) -BLENDERLIB(bf_editor_animation "${SRC}" "${INC}") +set(SRC + anim_channels_defines.c + anim_channels_edit.c + anim_deps.c + anim_draw.c + anim_filter.c + anim_ipo_utils.c + anim_markers.c + anim_ops.c + drivers.c + fmodifier_ui.c + keyframes_draw.c + keyframes_edit.c + keyframes_general.c + keyframing.c + keyingsets.c + + anim_intern.h +) + +blender_add_lib(bf_editor_animation "${SRC}" "${INC}") diff --git a/source/blender/editors/animation/Makefile b/source/blender/editors/animation/Makefile deleted file mode 100644 index f120091e917..00000000000 --- a/source/blender/editors/animation/Makefile +++ /dev/null @@ -1,54 +0,0 @@ -# -# $Id$ -# -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# The Original Code is Copyright (C) 2007 Blender Foundation -# All rights reserved. -# -# The Original Code is: all of this file. -# -# Contributor(s): none yet. -# -# ***** END GPL LICENSE BLOCK ***** -# -# Makes module object directory and bounces make to subdirectories. - -LIBNAME = ed_animation -DIR = $(OCGDIR)/blender/$(LIBNAME) - -include nan_compile.mk - -CFLAGS += $(LEVEL_1_C_WARNINGS) - -CPPFLAGS += -I$(NAN_GLEW)/include -CPPFLAGS += -I$(OPENGL_HEADERS) - -# not very neat.... -CPPFLAGS += -I../../windowmanager -CPPFLAGS += -I../../blenloader -CPPFLAGS += -I../../blenkernel -CPPFLAGS += -I../../blenlib -CPPFLAGS += -I../../makesdna -CPPFLAGS += -I../../makesrna -CPPFLAGS += -I../../imbuf -CPPFLAGS += -I../../python -CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include - -# own include - -CPPFLAGS += -I../include diff --git a/source/blender/editors/animation/SConscript b/source/blender/editors/animation/SConscript index ec4b577b349..17f8d32ccf1 100644 --- a/source/blender/editors/animation/SConscript +++ b/source/blender/editors/animation/SConscript @@ -4,7 +4,11 @@ Import ('env') sources = env.Glob('*.c') incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../makesrna ../../imbuf' +<<<<<<< .working incs += ' ../../windowmanager ../../bmesh' incs += ' #/intern/guardedalloc #/extern/glew/include' +======= +incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include ../../blenloader' +>>>>>>> .merge-right.r35190 env.BlenderLib ( 'bf_editors_animation', sources, Split(incs), [], libtype=['core'], priority=[125] ) diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index 09fbdf2d70d..1e2112bf82f 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -25,12 +25,13 @@ * ***** END GPL LICENSE BLOCK ***** */ - +#include <stdio.h> #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" #include "BLI_math.h" +#include "BLI_utildefines.h" #include "DNA_anim_types.h" #include "DNA_armature_types.h" @@ -42,16 +43,20 @@ #include "DNA_space_types.h" #include "DNA_key_types.h" #include "DNA_lamp_types.h" +#include "DNA_lattice_types.h" #include "DNA_mesh_types.h" #include "DNA_material_types.h" #include "DNA_meta_types.h" #include "DNA_node_types.h" #include "DNA_world_types.h" +#include "DNA_gpencil_types.h" #include "RNA_access.h" + #include "BKE_curve.h" #include "BKE_key.h" #include "BKE_context.h" +#include "BKE_utildefines.h" /* FILE_MAX */ #include "UI_interface.h" #include "UI_interface_icons.h" @@ -61,6 +66,7 @@ #include "ED_keyframing.h" #include "BIF_gl.h" +#include "BIF_glutil.h" #include "WM_api.h" #include "WM_types.h" @@ -74,6 +80,8 @@ /* size of indent steps */ #define INDENT_STEP_SIZE 7 +#define ANIM_CHAN_NAME_SIZE 256 + /* macros used for type defines */ /* get the pointer used for some flag */ #define GET_ACF_FLAG_PTR(ptr) \ @@ -83,18 +91,13 @@ } -/* XXX */ -extern void gl_round_box(int mode, float minx, float miny, float maxx, float maxy, float rad); -extern void gl_round_box_shade(int mode, float minx, float miny, float maxx, float maxy, float rad, float shadetop, float shadedown); - - /* *********************************************** */ /* Generic Functions (Type independent) */ /* Draw Backdrop ---------------------------------- */ /* get backdrop color for top-level widgets (Scene and Object only) */ -static void acf_generic_root_color(bAnimContext *ac, bAnimListElem *ale, float *color) +static void acf_generic_root_color(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), float *color) { /* darker blue for top-level widgets */ UI_GetThemeColor3fv(TH_DOPESHEET_CHANNELOB, color); @@ -115,12 +118,12 @@ static void acf_generic_root_backdrop(bAnimContext *ac, bAnimListElem *ale, floa /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */ uiSetRoundBox((expanded)? (1):(1|8)); - gl_round_box(GL_POLYGON, offset, yminc, v2d->cur.xmax+EXTRA_SCROLL_PAD, ymaxc, 8); + uiDrawBox(GL_POLYGON, offset, yminc, v2d->cur.xmax+EXTRA_SCROLL_PAD, ymaxc, 8); } /* get backdrop color for data expanders under top-level Scene/Object */ -static void acf_generic_dataexpand_color(bAnimContext *ac, bAnimListElem *ale, float *color) +static void acf_generic_dataexpand_color(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), float *color) { /* lighter color than top-level widget */ UI_GetThemeColor3fv(TH_DOPESHEET_CHANNELSUBOB, color); @@ -166,7 +169,7 @@ static void acf_generic_channel_color(bAnimContext *ac, bAnimListElem *ale, floa if ( (saction && !(saction->flag & SACTION_NODRAWGCOLORS)) && ((grp) && (grp->customCol)) ) { - char cp[3]; + unsigned char cp[3]; if (indent == 2) { VECCOPY(cp, grp->cs.solid); @@ -207,11 +210,11 @@ static void acf_generic_channel_backdrop(bAnimContext *ac, bAnimListElem *ale, f /* Indention + Offset ------------------------------------------- */ /* indention level is always the value in the name */ -static short acf_generic_indention_0(bAnimContext *ac, bAnimListElem *ale) +static short acf_generic_indention_0(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale)) { return 0; } -static short acf_generic_indention_1(bAnimContext *ac, bAnimListElem *ale) +static short acf_generic_indention_1(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale)) { return 1; } @@ -223,7 +226,7 @@ static short acf_generic_indention_2(bAnimContext *ac, bAnimListElem *ale) #endif /* indention which varies with the grouping status */ -static short acf_generic_indention_flexible(bAnimContext *ac, bAnimListElem *ale) +static short acf_generic_indention_flexible(bAnimContext *UNUSED(ac), bAnimListElem *ale) { short indent= 0; @@ -303,7 +306,7 @@ static void acf_generic_idblock_name(bAnimListElem *ale, char *name) /* just copy the name... */ if (id && name) - strcpy(name, id->name+2); + BLI_strncpy(name, id->name+2, ANIM_CHAN_NAME_SIZE); } /* Settings ------------------------------------------- */ @@ -357,7 +360,7 @@ static void *acf_generic_dsexpand_setting_ptr(bAnimListElem *ale, int setting, s } /* check if some setting exists for this object-based data-expander (datablock only) */ -static short acf_generic_dataexpand_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting) +static short acf_generic_dataexpand_setting_valid(bAnimContext *ac, bAnimListElem *UNUSED(ale), int setting) { switch (setting) { /* expand is always supported */ @@ -380,7 +383,7 @@ static short acf_generic_dataexpand_setting_valid(bAnimContext *ac, bAnimListEle /* Animation Summary ----------------------------------- */ /* get backdrop color for summary widget */ -static void acf_summary_color(bAnimContext *ac, bAnimListElem *ale, float *color) +static void acf_summary_color(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), float *color) { // FIXME: hardcoded color - same as the 'action' line in NLA // reddish color @@ -405,31 +408,31 @@ static void acf_summary_backdrop(bAnimContext *ac, bAnimListElem *ale, float ymi * - special hack: make the top a bit higher, since we are first... */ uiSetRoundBox((1|8)); - gl_round_box(GL_POLYGON, 0, yminc-2, v2d->cur.xmax+EXTRA_SCROLL_PAD, ymaxc, 8); + uiDrawBox(GL_POLYGON, 0, yminc-2, v2d->cur.xmax+EXTRA_SCROLL_PAD, ymaxc, 8); } /* name for summary entries */ -static void acf_summary_name(bAnimListElem *ale, char *name) +static void acf_summary_name(bAnimListElem *UNUSED(ale), char *name) { if (name) - strcpy(name, "DopeSheet Summary"); + BLI_strncpy(name, "DopeSheet Summary", ANIM_CHAN_NAME_SIZE); } // TODO: this is really a temp icon I think -static int acf_summary_icon(bAnimListElem *ale) +static int acf_summary_icon(bAnimListElem *UNUSED(ale)) { return ICON_BORDERMOVE; } /* check if some setting exists for this channel */ -static short acf_summary_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting) +static short acf_summary_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), int setting) { /* only expanded is supported, as it is used for hiding all stuff which the summary covers */ return (setting == ACHANNEL_SETTING_EXPAND); } /* get the appropriate flag(s) for the setting when it is valid */ -static int acf_summary_setting_flag(bAnimContext *ac, int setting, short *neg) +static int acf_summary_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { if (setting == ACHANNEL_SETTING_EXPAND) { /* expanded */ @@ -461,7 +464,7 @@ static void *acf_summary_setting_ptr(bAnimListElem *ale, int setting, short *typ else { /* can't return anything useful - unsupported */ *type= 0; - return 0; + return NULL; } } @@ -486,13 +489,13 @@ static bAnimChannelType ACF_SUMMARY = /* Scene ------------------------------------------- */ // TODO: just get this from RNA? -static int acf_scene_icon(bAnimListElem *ale) +static int acf_scene_icon(bAnimListElem *UNUSED(ale)) { return ICON_SCENE_DATA; } /* check if some setting exists for this channel */ -static short acf_scene_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting) +static short acf_scene_setting_valid(bAnimContext *ac, bAnimListElem *UNUSED(ale), int setting) { switch (setting) { /* muted only in NLA */ @@ -514,7 +517,7 @@ static short acf_scene_setting_valid(bAnimContext *ac, bAnimListElem *ale, int s } /* get the appropriate flag(s) for the setting when it is valid */ -static int acf_scene_setting_flag(bAnimContext *ac, int setting, short *neg) +static int acf_scene_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; @@ -562,7 +565,7 @@ static void *acf_scene_setting_ptr(bAnimListElem *ale, int setting, short *type) return NULL; default: /* unsupported */ - return 0; + return NULL; } } @@ -628,7 +631,7 @@ static void acf_object_name(bAnimListElem *ale, char *name) /* just copy the name... */ if (ob && name) - strcpy(name, ob->id.name+2); + BLI_strncpy(name, ob->id.name+2, ANIM_CHAN_NAME_SIZE); } /* check if some setting exists for this channel */ @@ -657,7 +660,7 @@ static short acf_object_setting_valid(bAnimContext *ac, bAnimListElem *ale, int } /* get the appropriate flag(s) for the setting when it is valid */ -static int acf_object_setting_flag(bAnimContext *ac, int setting, short *neg) +static int acf_object_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; @@ -706,7 +709,7 @@ static void *acf_object_setting_ptr(bAnimListElem *ale, int setting, short *type return NULL; default: /* unsupported */ - return 0; + return NULL; } } @@ -731,7 +734,7 @@ static bAnimChannelType ACF_OBJECT = /* Group ------------------------------------------- */ /* get backdrop color for group widget */ -static void acf_group_color(bAnimContext *ac, bAnimListElem *ale, float *color) +static void acf_group_color(bAnimContext *UNUSED(ac), bAnimListElem *ale, float *color) { /* highlight only for action group channels */ if (ale->flag & AGRP_ACTIVE) @@ -755,7 +758,7 @@ static void acf_group_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */ uiSetRoundBox((expanded)? (1):(1|8)); - gl_round_box(GL_POLYGON, offset, yminc, v2d->cur.xmax+EXTRA_SCROLL_PAD, ymaxc, 8); + uiDrawBox(GL_POLYGON, offset, yminc, v2d->cur.xmax+EXTRA_SCROLL_PAD, ymaxc, 8); } /* name for group entries */ @@ -765,11 +768,11 @@ static void acf_group_name(bAnimListElem *ale, char *name) /* just copy the name... */ if (agrp && name) - strcpy(name, agrp->name); + BLI_strncpy(name, agrp->name, ANIM_CHAN_NAME_SIZE); } /* check if some setting exists for this channel */ -static short acf_group_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting) +static short acf_group_setting_valid(bAnimContext *ac, bAnimListElem *UNUSED(ale), int setting) { /* for now, all settings are supported, though some are only conditionally */ switch (setting) { @@ -819,7 +822,7 @@ static int acf_group_setting_flag(bAnimContext *ac, int setting, short *neg) } /* get pointer to the setting */ -static void *acf_group_setting_ptr(bAnimListElem *ale, int setting, short *type) +static void *acf_group_setting_ptr(bAnimListElem *ale, int UNUSED(setting), short *type) { bActionGroup *agrp= (bActionGroup *)ale->data; @@ -880,7 +883,7 @@ static short acf_fcurve_setting_valid(bAnimContext *ac, bAnimListElem *ale, int } /* get the appropriate flag(s) for the setting when it is valid */ -static int acf_fcurve_setting_flag(bAnimContext *ac, int setting, short *neg) +static int acf_fcurve_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; @@ -905,7 +908,7 @@ static int acf_fcurve_setting_flag(bAnimContext *ac, int setting, short *neg) } /* get pointer to the setting */ -static void *acf_fcurve_setting_ptr(bAnimListElem *ale, int setting, short *type) +static void *acf_fcurve_setting_ptr(bAnimListElem *ale, int UNUSED(setting), short *type) { FCurve *fcu= (FCurve *)ale->data; @@ -934,13 +937,13 @@ static bAnimChannelType ACF_FCURVE = /* Object Action Expander ------------------------------------------- */ // TODO: just get this from RNA? -static int acf_fillactd_icon(bAnimListElem *ale) +static int acf_fillactd_icon(bAnimListElem *UNUSED(ale)) { return ICON_ACTION; } /* check if some setting exists for this channel */ -static short acf_fillactd_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting) +static short acf_fillactd_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), int setting) { switch (setting) { /* only select and expand supported */ @@ -954,7 +957,7 @@ static short acf_fillactd_setting_valid(bAnimContext *ac, bAnimListElem *ale, in } /* get the appropriate flag(s) for the setting when it is valid */ -static int acf_fillactd_setting_flag(bAnimContext *ac, int setting, short *neg) +static int acf_fillactd_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; @@ -987,13 +990,13 @@ static void *acf_fillactd_setting_ptr(bAnimListElem *ale, int setting, short *ty GET_ACF_FLAG_PTR(adt->flag); } else - return 0; + return NULL; case ACHANNEL_SETTING_EXPAND: /* expanded */ GET_ACF_FLAG_PTR(act->flag); default: /* unsupported */ - return 0; + return NULL; } } @@ -1018,19 +1021,19 @@ static bAnimChannelType ACF_FILLACTD = /* Drivers Expander ------------------------------------------- */ // TODO: just get this from RNA? -static int acf_filldrivers_icon(bAnimListElem *ale) +static int acf_filldrivers_icon(bAnimListElem *UNUSED(ale)) { return ICON_ANIM_DATA; } -static void acf_filldrivers_name(bAnimListElem *ale, char *name) +static void acf_filldrivers_name(bAnimListElem *UNUSED(ale), char *name) { - strcpy(name, "Drivers"); + BLI_strncpy(name, "Drivers", ANIM_CHAN_NAME_SIZE); } /* check if some setting exists for this channel */ // TODO: this could be made more generic -static short acf_filldrivers_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting) +static short acf_filldrivers_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), int setting) { switch (setting) { /* only expand supported */ @@ -1043,7 +1046,7 @@ static short acf_filldrivers_setting_valid(bAnimContext *ac, bAnimListElem *ale, } /* get the appropriate flag(s) for the setting when it is valid */ -static int acf_filldrivers_setting_flag(bAnimContext *ac, int setting, short *neg) +static int acf_filldrivers_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; @@ -1071,7 +1074,7 @@ static void *acf_filldrivers_setting_ptr(bAnimListElem *ale, int setting, short GET_ACF_FLAG_PTR(adt->flag); default: /* unsupported */ - return 0; + return NULL; } } @@ -1096,18 +1099,18 @@ static bAnimChannelType ACF_FILLDRIVERS = /* Materials Expander ------------------------------------------- */ // TODO: just get this from RNA? -static int acf_fillmatd_icon(bAnimListElem *ale) +static int acf_fillmatd_icon(bAnimListElem *UNUSED(ale)) { return ICON_MATERIAL_DATA; } -static void acf_fillmatd_name(bAnimListElem *ale, char *name) +static void acf_fillmatd_name(bAnimListElem *UNUSED(ale), char *name) { - strcpy(name, "Materials"); + BLI_strncpy(name, "Materials", ANIM_CHAN_NAME_SIZE); } /* get the appropriate flag(s) for the setting when it is valid */ -static int acf_fillmatd_setting_flag(bAnimContext *ac, int setting, short *neg) +static int acf_fillmatd_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; @@ -1142,18 +1145,18 @@ static bAnimChannelType ACF_FILLMATD= /* Particles Expander ------------------------------------------- */ // TODO: just get this from RNA? -static int acf_fillpartd_icon(bAnimListElem *ale) +static int acf_fillpartd_icon(bAnimListElem *UNUSED(ale)) { return ICON_PARTICLE_DATA; } -static void acf_fillpartd_name(bAnimListElem *ale, char *name) +static void acf_fillpartd_name(bAnimListElem *UNUSED(ale), char *name) { - strcpy(name, "Particles"); + BLI_strncpy(name, "Particles", ANIM_CHAN_NAME_SIZE); } /* get the appropriate flag(s) for the setting when it is valid */ -static int acf_fillpartd_setting_flag(bAnimContext *ac, int setting, short *neg) +static int acf_fillpartd_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; @@ -1210,14 +1213,14 @@ static short acf_filltexd_offset(bAnimContext *ac, bAnimListElem *ale) } // TODO: just get this from RNA? -static int acf_filltexd_icon(bAnimListElem *ale) +static int acf_filltexd_icon(bAnimListElem *UNUSED(ale)) { return ICON_TEXTURE_DATA; } -static void acf_filltexd_name(bAnimListElem *ale, char *name) +static void acf_filltexd_name(bAnimListElem *UNUSED(ale), char *name) { - strcpy(name, "Textures"); + BLI_strncpy(name, "Textures", ANIM_CHAN_NAME_SIZE); } /* get pointer to the setting (category only) */ @@ -1258,7 +1261,7 @@ static void *acf_filltexd_setting_ptr(bAnimListElem *ale, int setting, short *ty } /* get the appropriate flag(s) for the setting when it is valid */ -static int acf_filltexd_setting_flag(bAnimContext *ac, int setting, short *neg) +static int acf_filltexd_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; @@ -1294,19 +1297,19 @@ static bAnimChannelType ACF_FILLTEXD= /* Material Expander ------------------------------------------- */ // TODO: just get this from RNA? -static int acf_dsmat_icon(bAnimListElem *ale) +static int acf_dsmat_icon(bAnimListElem *UNUSED(ale)) { return ICON_MATERIAL_DATA; } /* offset for material expanders */ -static short acf_dsmat_offset(bAnimContext *ac, bAnimListElem *ale) +static short acf_dsmat_offset(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale)) { return 21; } /* get the appropriate flag(s) for the setting when it is valid */ -static int acf_dsmat_setting_flag(bAnimContext *ac, int setting, short *neg) +static int acf_dsmat_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; @@ -1376,13 +1379,13 @@ static bAnimChannelType ACF_DSMAT= /* Lamp Expander ------------------------------------------- */ // TODO: just get this from RNA? -static int acf_dslam_icon(bAnimListElem *ale) +static int acf_dslam_icon(bAnimListElem *UNUSED(ale)) { return ICON_LAMP_DATA; } /* get the appropriate flag(s) for the setting when it is valid */ -static int acf_dslam_setting_flag(bAnimContext *ac, int setting, short *neg) +static int acf_dslam_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; @@ -1452,13 +1455,13 @@ static bAnimChannelType ACF_DSLAM= /* Texture Expander ------------------------------------------- */ // TODO: just get this from RNA? -static int acf_dstex_icon(bAnimListElem *ale) +static int acf_dstex_icon(bAnimListElem *UNUSED(ale)) { return ICON_TEXTURE_DATA; } /* offset for texture expanders */ -static short acf_dstex_offset(bAnimContext *ac, bAnimListElem *ale) +static short acf_dstex_offset(bAnimContext *UNUSED(ac), bAnimListElem *ale) { short offset = 21; @@ -1477,7 +1480,7 @@ static short acf_dstex_offset(bAnimContext *ac, bAnimListElem *ale) } /* get the appropriate flag(s) for the setting when it is valid */ -static int acf_dstex_setting_flag(bAnimContext *ac, int setting, short *neg) +static int acf_dstex_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; @@ -1547,13 +1550,13 @@ static bAnimChannelType ACF_DSTEX= /* Camera Expander ------------------------------------------- */ // TODO: just get this from RNA? -static int acf_dscam_icon(bAnimListElem *ale) +static int acf_dscam_icon(bAnimListElem *UNUSED(ale)) { return ICON_CAMERA_DATA; } /* get the appropriate flag(s) for the setting when it is valid */ -static int acf_dscam_setting_flag(bAnimContext *ac, int setting, short *neg) +static int acf_dscam_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; @@ -1639,7 +1642,7 @@ static int acf_dscur_icon(bAnimListElem *ale) } /* get the appropriate flag(s) for the setting when it is valid */ -static int acf_dscur_setting_flag(bAnimContext *ac, int setting, short *neg) +static int acf_dscur_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; @@ -1709,13 +1712,13 @@ static bAnimChannelType ACF_DSCUR= /* Shape Key Expander ------------------------------------------- */ // TODO: just get this from RNA? -static int acf_dsskey_icon(bAnimListElem *ale) +static int acf_dsskey_icon(bAnimListElem *UNUSED(ale)) { return ICON_SHAPEKEY_DATA; } /* get the appropriate flag(s) for the setting when it is valid */ -static int acf_dsskey_setting_flag(bAnimContext *ac, int setting, short *neg) +static int acf_dsskey_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; @@ -1785,13 +1788,13 @@ static bAnimChannelType ACF_DSSKEY= /* World Expander ------------------------------------------- */ // TODO: just get this from RNA? -static int acf_dswor_icon(bAnimListElem *ale) +static int acf_dswor_icon(bAnimListElem *UNUSED(ale)) { return ICON_WORLD_DATA; } /* get the appropriate flag(s) for the setting when it is valid */ -static int acf_dswor_setting_flag(bAnimContext *ac, int setting, short *neg) +static int acf_dswor_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; @@ -1861,13 +1864,13 @@ static bAnimChannelType ACF_DSWOR= /* Particle Expander ------------------------------------------- */ // TODO: just get this from RNA? -static int acf_dspart_icon(bAnimListElem *ale) +static int acf_dspart_icon(bAnimListElem *UNUSED(ale)) { return ICON_PARTICLE_DATA; } /* get the appropriate flag(s) for the setting when it is valid */ -static int acf_dspart_setting_flag(bAnimContext *ac, int setting, short *neg) +static int acf_dspart_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; @@ -1937,13 +1940,13 @@ static bAnimChannelType ACF_DSPART= /* MetaBall Expander ------------------------------------------- */ // TODO: just get this from RNA? -static int acf_dsmball_icon(bAnimListElem *ale) +static int acf_dsmball_icon(bAnimListElem *UNUSED(ale)) { return ICON_META_DATA; } /* get the appropriate flag(s) for the setting when it is valid */ -static int acf_dsmball_setting_flag(bAnimContext *ac, int setting, short *neg) +static int acf_dsmball_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; @@ -2013,13 +2016,13 @@ static bAnimChannelType ACF_DSMBALL= /* Armature Expander ------------------------------------------- */ // TODO: just get this from RNA? -static int acf_dsarm_icon(bAnimListElem *ale) +static int acf_dsarm_icon(bAnimListElem *UNUSED(ale)) { return ICON_ARMATURE_DATA; } /* get the appropriate flag(s) for the setting when it is valid */ -static int acf_dsarm_setting_flag(bAnimContext *ac, int setting, short *neg) +static int acf_dsarm_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; @@ -2089,13 +2092,13 @@ static bAnimChannelType ACF_DSARM= /* NodeTree Expander ------------------------------------------- */ // TODO: just get this from RNA? -static int acf_dsntree_icon(bAnimListElem *ale) +static int acf_dsntree_icon(bAnimListElem *UNUSED(ale)) { return ICON_NODETREE; } /* get the appropriate flag(s) for the setting when it is valid */ -static int acf_dsntree_setting_flag(bAnimContext *ac, int setting, short *neg) +static int acf_dsntree_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; @@ -2165,13 +2168,13 @@ static bAnimChannelType ACF_DSNTREE= /* Mesh Expander ------------------------------------------- */ // TODO: just get this from RNA? -static int acf_dsmesh_icon(bAnimListElem *ale) +static int acf_dsmesh_icon(bAnimListElem *UNUSED(ale)) { return ICON_MESH_DATA; } /* get the appropriate flag(s) for the setting when it is valid */ -static int acf_dsmesh_setting_flag(bAnimContext *ac, int setting, short *neg) +static int acf_dsmesh_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; @@ -2238,6 +2241,82 @@ static bAnimChannelType ACF_DSMESH= acf_dsmesh_setting_ptr /* pointer for setting */ }; +/* Lattice Expander ------------------------------------------- */ + +// TODO: just get this from RNA? +static int acf_dslat_icon(bAnimListElem *UNUSED(ale)) +{ + return ICON_LATTICE_DATA; +} + +/* get the appropriate flag(s) for the setting when it is valid */ +static int acf_dslat_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) +{ + /* clear extra return data first */ + *neg= 0; + + switch (setting) { + case ACHANNEL_SETTING_EXPAND: /* expanded */ + return LT_DS_EXPAND; + + case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */ + return ADT_NLA_EVAL_OFF; + + case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */ + *neg= 1; + return ADT_CURVES_NOT_VISIBLE; + + case ACHANNEL_SETTING_SELECT: /* selected */ + return ADT_UI_SELECTED; + + default: /* unsupported */ + return 0; + } +} + +/* get pointer to the setting */ +static void *acf_dslat_setting_ptr(bAnimListElem *ale, int setting, short *type) +{ + Lattice *lt= (Lattice *)ale->data; + + /* clear extra return data first */ + *type= 0; + + switch (setting) { + case ACHANNEL_SETTING_EXPAND: /* expanded */ + GET_ACF_FLAG_PTR(lt->flag); + + case ACHANNEL_SETTING_SELECT: /* selected */ + case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */ + case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */ + if (lt->adt) + GET_ACF_FLAG_PTR(lt->adt->flag) + else + return NULL; + + default: /* unsupported */ + return NULL; + } +} + +/* node tree expander type define */ +static bAnimChannelType ACF_DSLAT= +{ + "Lattice Expander", /* type name */ + + acf_generic_dataexpand_color, /* backdrop color */ + acf_generic_dataexpand_backdrop,/* backdrop */ + acf_generic_indention_1, /* indent level */ // XXX this only works for compositing + acf_generic_basic_offset, /* offset */ + + acf_generic_idblock_name, /* name */ + acf_dslat_icon, /* icon */ + + acf_generic_dataexpand_setting_valid, /* has setting */ + acf_dslat_setting_flag, /* flag for setting */ + acf_dslat_setting_ptr /* pointer for setting */ +}; + /* ShapeKey Entry ------------------------------------------- */ /* name for ShapeKey */ @@ -2249,14 +2328,14 @@ static void acf_shapekey_name(bAnimListElem *ale, char *name) if (kb && name) { /* if the KeyBlock had a name, use it, otherwise use the index */ if (kb->name[0]) - strcpy(name, kb->name); + BLI_strncpy(name, kb->name, ANIM_CHAN_NAME_SIZE); else - sprintf(name, "Key %d", ale->index); + BLI_snprintf(name, ANIM_CHAN_NAME_SIZE, "Key %d", ale->index); } } /* check if some setting exists for this channel */ -static short acf_shapekey_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting) +static short acf_shapekey_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), int setting) { switch (setting) { case ACHANNEL_SETTING_SELECT: /* selected */ @@ -2271,7 +2350,7 @@ static short acf_shapekey_setting_valid(bAnimContext *ac, bAnimListElem *ale, in } /* get the appropriate flag(s) for the setting when it is valid */ -static int acf_shapekey_setting_flag(bAnimContext *ac, int setting, short *neg) +static int acf_shapekey_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; @@ -2328,126 +2407,154 @@ static bAnimChannelType ACF_SHAPEKEY= acf_shapekey_setting_ptr /* pointer for setting */ }; -/* Grease Pencil entries ------------------------------------------- */ -// XXX ... this is currently not restored yet +/* GPencil Datablock ------------------------------------------- */ -#if 0 -static void dummy_olddraw_gpencil () +/* get backdrop color for gpencil datablock widget */ +static void acf_gpd_color(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), float *color) { - /* determine what needs to be drawn */ - switch (ale->type) { - case ANIMTYPE_GPDATABLOCK: /* gpencil datablock */ - { - bGPdata *gpd = (bGPdata *)ale->data; - ScrArea *sa = (ScrArea *)ale->owner; // XXX depreceated... - - indent = 0; - group= 3; + /* these are ID-blocks, but not exactly standalone... */ + UI_GetThemeColorShade3fv(TH_DOPESHEET_CHANNELSUBOB, 20, color); +} + +// TODO: just get this from RNA? +static int acf_gpd_icon(bAnimListElem *UNUSED(ale)) +{ + return ICON_GREASEPENCIL; +} + +/* check if some setting exists for this channel */ +static short acf_gpd_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), int setting) +{ + switch (setting) { + /* only select and expand supported */ + case ACHANNEL_SETTING_SELECT: + case ACHANNEL_SETTING_EXPAND: + return 1; - /* only show expand if there are any channels */ - if (gpd->layers.first) { - if (gpd->flag & GP_DATA_EXPAND) - expand = ICON_TRIA_DOWN; - else - expand = ICON_TRIA_RIGHT; - } + default: + return 0; + } +} + +/* get the appropriate flag(s) for the setting when it is valid */ +static int acf_gpd_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) +{ + /* clear extra return data first */ + *neg= 0; + + switch (setting) { + case ACHANNEL_SETTING_SELECT: /* selected */ + return AGRP_SELECTED; - switch (sa->spacetype) { - case SPACE_VIEW3D: - { - /* this shouldn't cause any overflow... */ - //sprintf(name, "View3D:%s", view3d_get_name(sa->spacedata.first)); // XXX missing func.. - strcpy(name, "View3D"); - special= ICON_VIEW3D; - } - break; - case SPACE_NODE: - { - SpaceNode *snode= sa->spacedata.first; - char treetype[12]; - - if (snode->treetype == 1) - strcpy(treetype, "Composite"); - else - strcpy(treetype, "Material"); - sprintf(name, "Nodes:%s", treetype); - - special= ICON_NODETREE; - } - break; - case SPACE_SEQ: - { - SpaceSeq *sseq= sa->spacedata.first; - char imgpreview[10]; - - switch (sseq->mainb) { - case 1: sprintf(imgpreview, "Image..."); break; - case 2: sprintf(imgpreview, "Luma..."); break; - case 3: sprintf(imgpreview, "Chroma..."); break; - case 4: sprintf(imgpreview, "Histogram"); break; - - default: sprintf(imgpreview, "Sequence"); break; - } - sprintf(name, "Sequencer:%s", imgpreview); - - special= ICON_SEQUENCE; - } - break; - case SPACE_IMAGE: - { - SpaceImage *sima= sa->spacedata.first; - - if (sima->image) - sprintf(name, "Image:%s", sima->image->id.name+2); - else - strcpy(name, "Image:<None>"); - - special= ICON_IMAGE_COL; - } - break; - - default: - { - sprintf(name, "<Unknown GP-Data Source>"); - special= -1; - } - break; - } - } - break; - case ANIMTYPE_GPLAYER: /* gpencil layer */ - { - bGPDlayer *gpl = (bGPDlayer *)ale->data; + case ACHANNEL_SETTING_EXPAND: /* expanded */ + return GP_DATA_EXPAND; + } + + /* this shouldn't happen */ + return 0; +} + +/* get pointer to the setting */ +static void *acf_gpd_setting_ptr(bAnimListElem *ale, int UNUSED(setting), short *type) +{ + bGPdata *gpd= (bGPdata *)ale->data; + + /* all flags are just in gpd->flag for now... */ + GET_ACF_FLAG_PTR(gpd->flag); +} + +/* gpencil datablock type define */ +static bAnimChannelType ACF_GPD = +{ + "GPencil Datablock", /* type name */ + + acf_gpd_color, /* backdrop color */ + acf_group_backdrop, /* backdrop */ + acf_generic_indention_0, /* indent level */ + acf_generic_group_offset, /* offset */ + + acf_generic_idblock_name, /* name */ + acf_gpd_icon, /* icon */ + + acf_gpd_setting_valid, /* has setting */ + acf_gpd_setting_flag, /* flag for setting */ + acf_gpd_setting_ptr /* pointer for setting */ +}; + +/* GPencil Layer ------------------------------------------- */ + +/* name for grase pencil layer entries */ +static void acf_gpl_name(bAnimListElem *ale, char *name) +{ + bGPDlayer *gpl = (bGPDlayer *)ale->data; + + if (gpl && name) + BLI_strncpy(name, gpl->info, ANIM_CHAN_NAME_SIZE); +} + +/* check if some setting exists for this channel */ +static short acf_gpl_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), int setting) +{ + switch (setting) { + /* unsupported */ + case ACHANNEL_SETTING_EXPAND: /* gpencil layers are more like F-Curves than groups */ + case ACHANNEL_SETTING_VISIBLE: /* graph editor only */ + return 0; + + /* always available */ + default: + return 1; + } +} + +/* get the appropriate flag(s) for the setting when it is valid */ +static int acf_gpl_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) +{ + /* clear extra return data first */ + *neg= 0; + + switch (setting) { + case ACHANNEL_SETTING_SELECT: /* selected */ + return GP_LAYER_SELECT; - indent = 0; - special = -1; - expand = -1; - group = 1; + case ACHANNEL_SETTING_MUTE: /* muted */ + return GP_LAYER_HIDE; - if (EDITABLE_GPL(gpl)) - protect = ICON_UNLOCKED; - else - protect = ICON_LOCKED; - - if (gpl->flag & GP_LAYER_HIDE) - mute = ICON_MUTE_IPO_ON; - else - mute = ICON_MUTE_IPO_OFF; + case ACHANNEL_SETTING_PROTECT: /* protected */ + //*neg= 1; - if we change this to edtiability + return GP_LAYER_LOCKED; - sel = SEL_GPL(gpl); - BLI_snprintf(name, 32, gpl->info); - } - break; - } - - if (group == 3) { - /* only for gp-data channels */ - UI_ThemeColorShade(TH_GROUP, 20); - uiSetRoundBox((expand == ICON_TRIA_DOWN)? (1):(1|8)); - gl_round_box(GL_POLYGON, x+offset, yminc, (float)ACHANNEL_NAMEWIDTH, ymaxc, 8); + default: /* unsupported */ + return 0; } } -#endif + +/* get pointer to the setting */ +static void *acf_gpl_setting_ptr(bAnimListElem *ale, int UNUSED(setting), short *type) +{ + bGPDlayer *gpl= (bGPDlayer *)ale->data; + + /* all flags are just in agrp->flag for now... */ + GET_ACF_FLAG_PTR(gpl->flag); +} + +/* grease pencil layer type define */ +static bAnimChannelType ACF_GPL = +{ + "GPencil Layer", /* type name */ + + acf_generic_channel_color, /* backdrop color */ + acf_generic_channel_backdrop, /* backdrop */ + acf_generic_indention_flexible, /* indent level */ + acf_generic_group_offset, /* offset */ + + acf_gpl_name, /* name */ + NULL, /* icon */ + + acf_gpl_setting_valid, /* has setting */ + acf_gpl_setting_flag, /* flag for setting */ + acf_gpl_setting_ptr /* pointer for setting */ +}; /* *********************************************** */ /* Type Registration and General Access */ @@ -2457,7 +2564,7 @@ static bAnimChannelType *animchannelTypeInfo[ANIMTYPE_NUM_TYPES]; static short ACF_INIT= 1; /* when non-zero, the list needs to be updated */ /* Initialise type info definitions */ -void ANIM_init_channel_typeinfo_data (void) +static void ANIM_init_channel_typeinfo_data (void) { int type= 0; @@ -2494,12 +2601,12 @@ void ANIM_init_channel_typeinfo_data (void) animchannelTypeInfo[type++]= &ACF_DSARM; /* Armature Channel */ animchannelTypeInfo[type++]= &ACF_DSMESH; /* Mesh Channel */ animchannelTypeInfo[type++]= &ACF_DSTEX; /* Texture Channel */ + animchannelTypeInfo[type++]= &ACF_DSLAT; /* Lattice Channel */ animchannelTypeInfo[type++]= &ACF_SHAPEKEY; /* ShapeKey */ - // XXX not restored yet - animchannelTypeInfo[type++]= NULL; /* Grease Pencil Datablock */ - animchannelTypeInfo[type++]= NULL; /* Grease Pencil Layer */ + animchannelTypeInfo[type++]= &ACF_GPD; /* Grease Pencil Datablock */ + animchannelTypeInfo[type++]= &ACF_GPL; /* Grease Pencil Layer */ // TODO: these types still need to be implemented!!! // probably need a few extra flags for these special cases... @@ -2538,14 +2645,14 @@ void ANIM_channel_debug_print_info (bAnimListElem *ale, short indent_level) /* print info */ if (acf) { - char name[256]; /* hopefully this will be enough! */ + char name[ANIM_CHAN_NAME_SIZE]; /* hopefully this will be enough! */ /* get UI name */ if (acf->name) acf->name(ale, name); else - sprintf(name, "<No name>"); - + BLI_strncpy(name, "<No name>", sizeof(name)); + /* print type name + ui name */ printf("ChanType: <%s> Name: \"%s\"\n", acf->channel_type_name, name); } @@ -2777,7 +2884,7 @@ void ANIM_channel_draw (bAnimContext *ac, bAnimListElem *ale, float yminc, float /* step 5) draw name ............................................... */ if (acf->name) { - char name[256]; /* hopefully this will be enough! */ + char name[ANIM_CHAN_NAME_SIZE]; /* hopefully this will be enough! */ /* set text color */ if (selected) @@ -2790,6 +2897,17 @@ void ANIM_channel_draw (bAnimContext *ac, bAnimListElem *ale, float yminc, float offset += 3; UI_DrawString(offset, ytext, name); + + /* draw red underline if channel is disabled */ + if ((ale->type == ANIMTYPE_FCURVE) && (ale->flag & FCURVE_DISABLED)) + { + // FIXME: replace hardcoded color here, and check on extents! + glColor3f(1.0f, 0.0f, 0.0f); + glLineWidth(2.0); + fdrawline((float)(offset), yminc, + (float)(v2d->cur.xmax), yminc); + glLineWidth(1.0); + } } /* step 6) draw backdrops behidn mute+protection toggles + (sliders) ....................... */ @@ -2856,7 +2974,7 @@ void ANIM_channel_draw (bAnimContext *ac, bAnimListElem *ale, float yminc, float /* ------------------ */ /* callback for (normal) widget settings - send notifiers */ -static void achannel_setting_widget_cb(bContext *C, void *poin, void *poin2) +static void achannel_setting_widget_cb(bContext *C, void *UNUSED(arg1), void *UNUSED(arg2)) { WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN|NA_EDITED, NULL); } @@ -2910,6 +3028,7 @@ static void achannel_setting_slider_cb(bContext *C, void *id_poin, void *fcu_poi ID *id= (ID *)id_poin; FCurve *fcu= (FCurve *)fcu_poin; + ReportList *reports = CTX_wm_reports(C); Scene *scene= CTX_data_scene(C); PointerRNA id_ptr, ptr; PropertyRNA *prop; @@ -2933,7 +3052,7 @@ static void achannel_setting_slider_cb(bContext *C, void *id_poin, void *fcu_poi flag |= INSERTKEY_REPLACE; /* insert a keyframe for this F-Curve */ - done= insert_keyframe_direct(ptr, prop, fcu, cfra, flag); + done= insert_keyframe_direct(reports, ptr, prop, fcu, cfra, flag); if (done) WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN|NA_EDITED, NULL); @@ -2947,6 +3066,7 @@ static void achannel_setting_slider_shapekey_cb(bContext *C, void *key_poin, voi KeyBlock *kb= (KeyBlock *)kb_poin; char *rna_path= key_get_curValue_rnaPath(key, kb); + ReportList *reports = CTX_wm_reports(C); Scene *scene= CTX_data_scene(C); PointerRNA id_ptr, ptr; PropertyRNA *prop; @@ -2975,7 +3095,7 @@ static void achannel_setting_slider_shapekey_cb(bContext *C, void *key_poin, voi flag |= INSERTKEY_REPLACE; /* insert a keyframe for this F-Curve */ - done= insert_keyframe_direct(ptr, prop, fcu, cfra, flag); + done= insert_keyframe_direct(reports, ptr, prop, fcu, cfra, flag); if (done) WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN|NA_EDITED, NULL); @@ -2992,7 +3112,7 @@ static void draw_setting_widget (bAnimContext *ac, bAnimListElem *ale, bAnimChan short negflag, ptrsize, enabled, butType; int flag, icon; void *ptr; - char *tooltip; + const char *tooltip; uiBut *but = NULL; /* get the flag and the pointer to that flag */ @@ -3244,7 +3364,7 @@ void ANIM_channel_draw_widgets (bAnimContext *ac, bAnimListElem *ale, uiBlock *b uiBut *but; /* create the slider button, and assign relevant callback to ensure keyframes are inserted... */ - but= uiDefAutoButR(block, &ptr, prop, array_index, "", 0, (int)v2d->cur.xmax-offset, ymid, SLIDER_WIDTH, (int)ymaxc-yminc); + but= uiDefAutoButR(block, &ptr, prop, array_index, "", ICON_NULL, (int)v2d->cur.xmax-offset, ymid, SLIDER_WIDTH, (int)ymaxc-yminc); /* assign keyframing function according to slider type */ if (ale->type == ANIMTYPE_SHAPEKEY) diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index e229de42006..aa09cd0ac01 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -25,9 +25,15 @@ * ***** END GPL LICENSE BLOCK ***** */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" +#include "BLI_utildefines.h" + #include "DNA_anim_types.h" #include "DNA_object_types.h" @@ -110,6 +116,8 @@ void ANIM_set_active_channel (bAnimContext *ac, void *data, short datatype, int case ANIMTYPE_DSMBALL: case ANIMTYPE_DSARM: case ANIMTYPE_DSMESH: + case ANIMTYPE_DSTEX: + case ANIMTYPE_DSLAT: { /* need to verify that this data is valid for now */ if (ale->adt) { @@ -153,8 +161,10 @@ void ANIM_set_active_channel (bAnimContext *ac, void *data, short datatype, int case ANIMTYPE_DSMBALL: case ANIMTYPE_DSARM: case ANIMTYPE_DSMESH: + case ANIMTYPE_DSLAT: { /* need to verify that this data is valid for now */ + // XXX: ale may be null! if (ale->adt) ale->adt->flag |= ADT_UI_ACTIVE; } @@ -229,11 +239,17 @@ void ANIM_deselect_anim_channels (bAnimContext *ac, void *data, short datatype, case ANIMTYPE_DSMESH: case ANIMTYPE_DSNTREE: case ANIMTYPE_DSTEX: + case ANIMTYPE_DSLAT: { if ((ale->adt) && (ale->adt->flag & ADT_UI_SELECTED)) sel= ACHANNEL_SETFLAG_CLEAR; } break; + + case ANIMTYPE_GPLAYER: + if (ale->flag & GP_LAYER_SELECT) + sel= ACHANNEL_SETFLAG_CLEAR; + break; } } } @@ -312,6 +328,7 @@ void ANIM_deselect_anim_channels (bAnimContext *ac, void *data, short datatype, case ANIMTYPE_DSMESH: case ANIMTYPE_DSNTREE: case ANIMTYPE_DSTEX: + case ANIMTYPE_DSLAT: { /* need to verify that this data is valid for now */ if (ale->adt) { @@ -320,6 +337,14 @@ void ANIM_deselect_anim_channels (bAnimContext *ac, void *data, short datatype, } } break; + + case ANIMTYPE_GPLAYER: + { + bGPDlayer *gpl = (bGPDlayer *)ale->data; + + ACHANNEL_SET_FLAG(gpl, sel, GP_LAYER_SELECT); + } + break; } } @@ -462,7 +487,7 @@ void ANIM_flush_setting_anim_channels (bAnimContext *ac, ListBase *anim_data, bA break; /* store this level as the 'old' level now */ - prevLevel= level; + prevLevel= level; // XXX: prevLevel is unused } } } @@ -502,7 +527,7 @@ void ANIM_fcurve_delete_from_animdata (bAnimContext *ac, AnimData *adt, FCurve * /* ****************** Operator Utilities ********************************** */ /* poll callback for being in an Animation Editor channels list region */ -int animedit_poll_channels_active (bContext *C) +static int animedit_poll_channels_active (bContext *C) { ScrArea *sa= CTX_wm_area(C); @@ -518,7 +543,7 @@ int animedit_poll_channels_active (bContext *C) } /* poll callback for Animation Editor channels list region + not in NLA-tweakmode for NLA */ -int animedit_poll_channels_nla_tweakmode_off (bContext *C) +static int animedit_poll_channels_nla_tweakmode_off (bContext *C) { ScrArea *sa= CTX_wm_area(C); Scene *scene = CTX_data_scene(C); @@ -541,132 +566,65 @@ int animedit_poll_channels_nla_tweakmode_off (bContext *C) } /* ****************** Rearrange Channels Operator ******************* */ -/* This operator only works for Action Editor mode for now, as having it elsewhere makes things difficult */ - -#if 0 // XXX old animation system - needs to be updated for new system... /* constants for channel rearranging */ /* WARNING: don't change exising ones without modifying rearrange func accordingly */ enum { - REARRANGE_ACTCHAN_TOP= -2, - REARRANGE_ACTCHAN_UP= -1, - REARRANGE_ACTCHAN_DOWN= 1, - REARRANGE_ACTCHAN_BOTTOM= 2 + REARRANGE_ANIMCHAN_TOP= -2, + REARRANGE_ANIMCHAN_UP= -1, + REARRANGE_ANIMCHAN_DOWN= 1, + REARRANGE_ANIMCHAN_BOTTOM= 2 }; -/* make sure all action-channels belong to a group (and clear action's list) */ -static void split_groups_action_temp (bAction *act, bActionGroup *tgrp) -{ - bActionChannel *achan; - bActionGroup *agrp; - - /* Separate action-channels into lists per group */ - for (agrp= act->groups.first; agrp; agrp= agrp->next) { - if (agrp->channels.first) { - achan= agrp->channels.last; - act->chanbase.first= achan->next; - - achan= agrp->channels.first; - achan->prev= NULL; - - achan= agrp->channels.last; - achan->next= NULL; - } - } - - /* Initialise memory for temp-group */ - memset(tgrp, 0, sizeof(bActionGroup)); - tgrp->flag |= (AGRP_EXPANDED|AGRP_TEMP); - strcpy(tgrp->name, "#TempGroup"); - - /* Move any action-channels not already moved, to the temp group */ - if (act->chanbase.first) { - /* start of list */ - achan= act->chanbase.first; - achan->prev= NULL; - tgrp->channels.first= achan; - act->chanbase.first= NULL; - - /* end of list */ - achan= act->chanbase.last; - achan->next= NULL; - tgrp->channels.last= achan; - act->chanbase.last= NULL; - } - - /* Add temp-group to list */ - BLI_addtail(&act->groups, tgrp); -} +/* defines for rearranging channels */ +static EnumPropertyItem prop_animchannel_rearrange_types[] = { + {REARRANGE_ANIMCHAN_TOP, "TOP", 0, "To Top", ""}, + {REARRANGE_ANIMCHAN_UP, "UP", 0, "Up", ""}, + {REARRANGE_ANIMCHAN_DOWN, "DOWN", 0, "Down", ""}, + {REARRANGE_ANIMCHAN_BOTTOM, "BOTTOM", 0, "To Bottom", ""}, + {0, NULL, 0, NULL, NULL} +}; -/* link lists of channels that groups have */ -static void join_groups_action_temp (bAction *act) -{ - bActionGroup *agrp; - bActionChannel *achan; - - for (agrp= act->groups.first; agrp; agrp= agrp->next) { - ListBase tempGroup; - - /* add list of channels to action's channels */ - tempGroup= agrp->channels; - addlisttolist(&act->chanbase, &agrp->channels); - agrp->channels= tempGroup; - - /* clear moved flag */ - agrp->flag &= ~AGRP_MOVED; - - /* if temp-group... remove from list (but don't free as it's on the stack!) */ - if (agrp->flag & AGRP_TEMP) { - BLI_remlink(&act->groups, agrp); - break; - } - } +/* Reordering "Islands" Defines ----------------------------------- */ + +/* Island definition - just a listbase container */ +typedef struct tReorderChannelIsland { + struct tReorderChannelIsland *next, *prev; - /* clear "moved" flag from all achans */ - for (achan= act->chanbase.first; achan; achan= achan->next) - achan->flag &= ~ACHAN_MOVED; -} + ListBase channels; /* channels within this region with the same state */ + int flag; /* eReorderIslandFlag */ +} tReorderChannelIsland; +/* flags for channel reordering islands */ +typedef enum eReorderIslandFlag { + REORDER_ISLAND_SELECTED = (1<<0), /* island is selected */ + REORDER_ISLAND_UNTOUCHABLE = (1<<1), /* island should be ignored */ + REORDER_ISLAND_MOVED = (1<<2) /* island has already been moved */ +} eReorderIslandFlag; -static short rearrange_actchannel_is_ok (Link *channel, short type) -{ - if (type == ANIMTYPE_GROUP) { - bActionGroup *agrp= (bActionGroup *)channel; - - if (SEL_AGRP(agrp) && !(agrp->flag & AGRP_MOVED)) - return 1; - } - else if (type == ANIMTYPE_ACHAN) { - bActionChannel *achan= (bActionChannel *)channel; - - if (VISIBLE_ACHAN(achan) && SEL_ACHAN(achan) && !(achan->flag & ACHAN_MOVED)) - return 1; - } - - return 0; -} -static short rearrange_actchannel_after_ok (Link *channel, short type) +/* Rearrange Methods --------------------------------------------- */ + +static short rearrange_island_ok (tReorderChannelIsland *island) { - if (type == ANIMTYPE_GROUP) { - bActionGroup *agrp= (bActionGroup *)channel; - - if (agrp->flag & AGRP_TEMP) - return 0; - } + /* island must not be untouchable */ + if (island->flag & REORDER_ISLAND_UNTOUCHABLE) + return 0; - return 1; + /* island should be selected to be moved */ + return (island->flag & REORDER_ISLAND_SELECTED) && !(island->flag & REORDER_ISLAND_MOVED); } +/* ............................. */ -static short rearrange_actchannel_top (ListBase *list, Link *channel, short type) +static short rearrange_island_top (ListBase *list, tReorderChannelIsland *island) { - if (rearrange_actchannel_is_ok(channel, type)) { - /* take it out off the chain keep data */ - BLI_remlink(list, channel); + if (rearrange_island_ok(island)) { + /* remove from current position */ + BLI_remlink(list, island); /* make it first element */ - BLI_insertlinkbefore(list, list->first, channel); + BLI_insertlinkbefore(list, list->first, island); return 1; } @@ -674,17 +632,18 @@ static short rearrange_actchannel_top (ListBase *list, Link *channel, short type return 0; } -static short rearrange_actchannel_up (ListBase *list, Link *channel, short type) +static short rearrange_island_up (ListBase *list, tReorderChannelIsland *island) { - if (rearrange_actchannel_is_ok(channel, type)) { - Link *prev= channel->prev; + if (rearrange_island_ok(island)) { + /* moving up = moving before the previous island, otherwise we're in the same place */ + tReorderChannelIsland *prev= island->prev; if (prev) { - /* take it out off the chain keep data */ - BLI_remlink(list, channel); + /* remove from current position */ + BLI_remlink(list, island); /* push it up */ - BLI_insertlinkbefore(list, prev, channel); + BLI_insertlinkbefore(list, prev, island); return 1; } @@ -693,235 +652,442 @@ static short rearrange_actchannel_up (ListBase *list, Link *channel, short type) return 0; } -static short rearrange_actchannel_down (ListBase *list, Link *channel, short type) +static short rearrange_island_down (ListBase *list, tReorderChannelIsland *island) { - if (rearrange_actchannel_is_ok(channel, type)) { - Link *next = (channel->next) ? channel->next->next : NULL; + if (rearrange_island_ok(island)) { + /* moving down = moving after the next island, otherwise we're in the same place */ + tReorderChannelIsland *next = island->next; if (next) { - /* take it out off the chain keep data */ - BLI_remlink(list, channel); - - /* move it down */ - BLI_insertlinkbefore(list, next, channel); - - return 1; - } - else if (rearrange_actchannel_after_ok(list->last, type)) { - /* take it out off the chain keep data */ - BLI_remlink(list, channel); - - /* add at end */ - BLI_addtail(list, channel); - - return 1; - } - else { - /* take it out off the chain keep data */ - BLI_remlink(list, channel); - - /* add just before end */ - BLI_insertlinkbefore(list, list->last, channel); - - return 1; + /* can only move past if next is not untouchable (i.e. nothing can go after it) */ + if ((next->flag & REORDER_ISLAND_UNTOUCHABLE)==0) { + /* remove from current position */ + BLI_remlink(list, island); + + /* push it down */ + BLI_insertlinkafter(list, next, island); + + return 1; + } } + /* else: no next channel, so we're at the bottom already, so can't move */ } return 0; } -static short rearrange_actchannel_bottom (ListBase *list, Link *channel, short type) +static short rearrange_island_bottom (ListBase *list, tReorderChannelIsland *island) { - if (rearrange_actchannel_is_ok(channel, type)) { - if (rearrange_actchannel_after_ok(list->last, type)) { - /* take it out off the chain keep data */ - BLI_remlink(list, channel); - - /* add at end */ - BLI_addtail(list, channel); + if (rearrange_island_ok(island)) { + tReorderChannelIsland *last = list->last; + + /* remove island from current position */ + BLI_remlink(list, island); + + /* add before or after the last channel? */ + if ((last->flag & REORDER_ISLAND_UNTOUCHABLE)==0) { + /* can add after it */ + BLI_addtail(list, island); + } + else { + /* can at most go just before it, since last cannot be moved */ + BLI_insertlinkbefore(list, last, island); - return 1; } + + return 1; } return 0; } +/* ............................. */ -/* Change the order of action-channels - * mode: REARRANGE_ACTCHAN_* +/* typedef for channel rearranging function + * < list: list that channels belong to + * < island: island to be moved + * > return[0]: whether operation was a success */ -static void rearrange_action_channels (bAnimContext *ac, short mode) +typedef short (*AnimChanRearrangeFp)(ListBase *list, tReorderChannelIsland *island); + +/* get rearranging function, given 'rearrange' mode */ +static AnimChanRearrangeFp rearrange_get_mode_func (short mode) { - bAction *act; - bActionChannel *achan, *chan; - bActionGroup *agrp, *grp; - bActionGroup tgrp; - - short (*rearrange_func)(ListBase *, Link *, short); - short do_channels = 1; - - /* Get the active action, exit if none are selected */ - act= (bAction *)ac->data; - - /* exit if invalid mode */ switch (mode) { - case REARRANGE_ACTCHAN_TOP: - rearrange_func= rearrange_actchannel_top; - break; - case REARRANGE_ACTCHAN_UP: - rearrange_func= rearrange_actchannel_up; + case REARRANGE_ANIMCHAN_TOP: + return rearrange_island_top; + case REARRANGE_ANIMCHAN_UP: + return rearrange_island_up; + case REARRANGE_ANIMCHAN_DOWN: + return rearrange_island_down; + case REARRANGE_ANIMCHAN_BOTTOM: + return rearrange_island_bottom; + default: + return NULL; + } +} + +/* Rearrange Islands Generics ------------------------------------- */ + +/* add channel into list of islands */ +static void rearrange_animchannel_add_to_islands (ListBase *islands, ListBase *srcList, Link *channel, short type) +{ + tReorderChannelIsland *island = islands->last; /* always try to add to last island if possible */ + short is_sel=0, is_untouchable=0; + + /* get flags - selected and untouchable from the channel */ + switch (type) { + case ANIMTYPE_GROUP: + { + bActionGroup *agrp= (bActionGroup *)channel; + + is_sel= SEL_AGRP(agrp); + is_untouchable= (agrp->flag & AGRP_TEMP) != 0; + } break; - case REARRANGE_ACTCHAN_DOWN: - rearrange_func= rearrange_actchannel_down; + case ANIMTYPE_FCURVE: + { + FCurve *fcu= (FCurve *)channel; + + is_sel= SEL_FCU(fcu); + } break; - case REARRANGE_ACTCHAN_BOTTOM: - rearrange_func= rearrange_actchannel_bottom; + case ANIMTYPE_NLATRACK: + { + NlaTrack *nlt= (NlaTrack *)channel; + + is_sel= SEL_NLT(nlt); + } break; + default: + printf("rearrange_animchannel_add_to_islands(): don't know how to handle channels of type %d\n", type); return; } - /* make sure we're only operating with groups */ - split_groups_action_temp(act, &tgrp); + /* do we need to add to a new island? */ + if ((island == NULL) || /* 1) no islands yet */ + ((island->flag & REORDER_ISLAND_SELECTED) == 0) || /* 2) unselected islands have single channels only - to allow up/down movement */ + (is_sel == 0)) /* 3) if channel is unselected, stop existing island (it was either wrong sel status, or full already) */ + { + /* create a new island now */ + island = MEM_callocN(sizeof(tReorderChannelIsland), "tReorderChannelIsland"); + BLI_addtail(islands, island); + + if (is_sel) + island->flag |= REORDER_ISLAND_SELECTED; + if (is_untouchable) + island->flag |= REORDER_ISLAND_UNTOUCHABLE; + } + + /* add channel to island - need to remove it from its existing list first though */ + BLI_remlink(srcList, channel); + BLI_addtail(&island->channels, channel); +} + +/* flatten islands out into a single list again */ +static void rearrange_animchannel_flatten_islands (ListBase *islands, ListBase *srcList) +{ + tReorderChannelIsland *island, *isn=NULL; - /* rearrange groups first (and then, only consider channels if the groups weren't moved) */ - #define GET_FIRST(list) ((mode > 0) ? (list.first) : (list.last)) - #define GET_NEXT(item) ((mode > 0) ? (item->next) : (item->prev)) + /* make sure srcList is empty now */ + BLI_assert(srcList->first == NULL); - for (agrp= GET_FIRST(act->groups); agrp; agrp= grp) { - /* Get next group to consider */ - grp= GET_NEXT(agrp); + /* go through merging islands */ + for (island = islands->first; island; island = isn) { + isn = island->next; - /* try to do group first */ - if (rearrange_func(&act->groups, (Link *)agrp, ANIMTYPE_GROUP)) { - do_channels= 0; - agrp->flag |= AGRP_MOVED; - } + /* merge island channels back to main list, then delete the island */ + BLI_movelisttolist(srcList, &island->channels); + BLI_freelinkN(islands, island); + } +} + +/* ............................. */ + +/* performing rearranging of channels using islands */ +static short rearrange_animchannel_islands (ListBase *list, AnimChanRearrangeFp rearrange_func, short mode, short type) +{ + ListBase islands = {NULL, NULL}; + Link *channel, *chanNext=NULL; + short done = 0; + + /* don't waste effort on an empty list */ + if (list->first == NULL) + return 0; + + /* group channels into islands */ + for (channel = list->first; channel; channel = chanNext) { + chanNext = channel->next; + rearrange_animchannel_add_to_islands(&islands, list, channel, type); } - if (do_channels) { - for (agrp= GET_FIRST(act->groups); agrp; agrp= grp) { - /* Get next group to consider */ - grp= GET_NEXT(agrp); + /* perform moving of selected islands now, but only if there is more than one of 'em so that something will happen + * - scanning of the list is performed in the opposite direction to the direction we're moving things, so that we + * shouldn't need to encounter items we've moved already + */ + if (islands.first != islands.last) { + tReorderChannelIsland *first = (mode > 0) ? islands.last : islands.first; + tReorderChannelIsland *island, *isn=NULL; + + for (island = first; island; island = isn) { + isn = (mode > 0) ? island->prev : island->next; - /* only consider action-channels if they're visible (group expanded) */ - if (EXPANDED_AGRP(agrp)) { - for (achan= GET_FIRST(agrp->channels); achan; achan= chan) { - /* Get next channel to consider */ - chan= GET_NEXT(achan); - - /* Try to do channel */ - if (rearrange_func(&agrp->channels, (Link *)achan, ANIMTYPE_ACHAN)) - achan->flag |= ACHAN_MOVED; - } + /* perform rearranging */ + if (rearrange_func(&islands, island)) { + island->flag |= REORDER_ISLAND_MOVED; + done = 1; } } } - #undef GET_FIRST - #undef GET_NEXT - /* assemble lists into one list (and clear moved tags) */ - join_groups_action_temp(act); + /* ungroup islands */ + rearrange_animchannel_flatten_islands(&islands, list); + + /* did we do anything? */ + return done; } -/* ------------------- */ +/* NLA Specific Stuff ----------------------------------------------------- */ -static int animchannels_rearrange_exec(bContext *C, wmOperator *op) +/* Change the order NLA Tracks within NLA Stack + * ! NLA tracks are displayed in opposite order, so directions need care + * mode: REARRANGE_ANIMCHAN_* + */ +static void rearrange_nla_channels (bAnimContext *UNUSED(ac), AnimData *adt, short mode) { - bAnimContext ac; - short mode; + AnimChanRearrangeFp rearrange_func; - /* get editor data - only for Action Editor (for now) */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; - if (ac.datatype != ANIMCONT_ACTION) - return OPERATOR_PASS_THROUGH; - - /* get mode, then rearrange channels */ - mode= RNA_enum_get(op->ptr, "direction"); - rearrange_action_channels(&ac, mode); + /* hack: invert mode so that functions will work in right order */ + mode *= -1; - /* send notifier that things have changed */ - WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN|NA_EDITED, NULL); + /* get rearranging function */ + rearrange_func = rearrange_get_mode_func(mode); + if (rearrange_func == NULL) + return; - return OPERATOR_FINISHED; + /* only consider NLA data if it's accessible */ + //if (EXPANDED_DRVD(adt) == 0) + // return; + + /* perform rearranging on tracks list */ + rearrange_animchannel_islands(&adt->nla_tracks, rearrange_func, mode, ANIMTYPE_NLATRACK); } - -void ANIM_OT_channels_move_up (wmOperatorType *ot) +/* Drivers Specific Stuff ------------------------------------------------- */ + +/* Change the order drivers within AnimData block + * mode: REARRANGE_ANIMCHAN_* + */ +static void rearrange_driver_channels (bAnimContext *UNUSED(ac), AnimData *adt, short mode) { - /* identifiers */ - ot->name= "Move Channel(s) Up"; - ot->idname= "ANIM_OT_channels_move_up"; + /* get rearranging function */ + AnimChanRearrangeFp rearrange_func = rearrange_get_mode_func(mode); - /* api callbacks */ - ot->exec= animchannels_rearrange_exec; - ot->poll= ED_operator_areaactive; + if (rearrange_func == NULL) + return; - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + /* only consider drivers if they're accessible */ + if (EXPANDED_DRVD(adt) == 0) + return; - /* props */ - RNA_def_enum(ot->srna, "direction", NULL /* XXX add enum for this */, REARRANGE_ACTCHAN_UP, "Direction", ""); + /* perform rearranging on drivers list (drivers are really just F-Curves) */ + rearrange_animchannel_islands(&adt->drivers, rearrange_func, mode, ANIMTYPE_FCURVE); } -void ANIM_OT_channels_move_down (wmOperatorType *ot) +/* Action Specific Stuff ------------------------------------------------- */ + +/* make sure all action-channels belong to a group (and clear action's list) */ +static void split_groups_action_temp (bAction *act, bActionGroup *tgrp) { - /* identifiers */ - ot->name= "Move Channel(s) Down"; - ot->idname= "ANIM_OT_channels_move_down"; + bActionGroup *agrp; + FCurve *fcu; - /* api callbacks */ - ot->exec= animchannels_rearrange_exec; - ot->poll= ED_operator_areaactive; + if (act == NULL) + return; - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + /* Separate F-Curves into lists per group */ + for (agrp= act->groups.first; agrp; agrp= agrp->next) { + if (agrp->channels.first) { + fcu= agrp->channels.last; + act->curves.first= fcu->next; + + fcu= agrp->channels.first; + fcu->prev= NULL; + + fcu= agrp->channels.last; + fcu->next= NULL; + } + } - /* props */ - RNA_def_enum(ot->srna, "direction", NULL /* XXX add enum for this */, REARRANGE_ACTCHAN_DOWN, "Direction", ""); + /* Initialise memory for temp-group */ + memset(tgrp, 0, sizeof(bActionGroup)); + tgrp->flag |= (AGRP_EXPANDED|AGRP_TEMP); + BLI_strncpy(tgrp->name, "#TempGroup", sizeof(tgrp->name)); + + /* Move any action-channels not already moved, to the temp group */ + if (act->curves.first) { + /* start of list */ + fcu= act->curves.first; + fcu->prev= NULL; + tgrp->channels.first= fcu; + act->curves.first= NULL; + + /* end of list */ + fcu= act->curves.last; + fcu->next= NULL; + tgrp->channels.last= fcu; + act->curves.last= NULL; + } + + /* Add temp-group to list */ + BLI_addtail(&act->groups, tgrp); } -void ANIM_OT_channels_move_top (wmOperatorType *ot) +/* link lists of channels that groups have */ +static void join_groups_action_temp (bAction *act) { - /* identifiers */ - ot->name= "Move Channel(s) to Top"; - ot->idname= "ANIM_OT_channels_move_to_top"; + bActionGroup *agrp; - /* api callbacks */ - ot->exec= animchannels_rearrange_exec; - ot->poll= ED_operator_areaactive; + for (agrp= act->groups.first; agrp; agrp= agrp->next) { + ListBase tempGroup; + + /* add list of channels to action's channels */ + tempGroup= agrp->channels; + BLI_movelisttolist(&act->curves, &agrp->channels); + agrp->channels= tempGroup; + + /* clear moved flag */ + agrp->flag &= ~AGRP_MOVED; + + /* if temp-group... remove from list (but don't free as it's on the stack!) */ + if (agrp->flag & AGRP_TEMP) { + BLI_remlink(&act->groups, agrp); + break; + } + } +} + +/* Change the order of anim-channels within action + * mode: REARRANGE_ANIMCHAN_* + */ +static void rearrange_action_channels (bAnimContext *ac, bAction *act, short mode) +{ + bActionGroup tgrp; + short do_channels; - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + /* get rearranging function */ + AnimChanRearrangeFp rearrange_func = rearrange_get_mode_func(mode); - /* props */ - RNA_def_enum(ot->srna, "direction", NULL /* XXX add enum for this */, REARRANGE_ACTCHAN_TOP, "Direction", ""); + if (rearrange_func == NULL) + return; + + /* make sure we're only operating with groups (vs a mixture of groups+curves) */ + split_groups_action_temp(act, &tgrp); + + /* rearrange groups first + * - the group's channels will only get considered if nothing happened when rearranging the groups + * i.e. the rearrange function returned 0 + */ + do_channels = rearrange_animchannel_islands(&act->groups, rearrange_func, mode, ANIMTYPE_GROUP) == 0; + + if (do_channels) { + bActionGroup *agrp; + + for (agrp= act->groups.first; agrp; agrp= agrp->next) { + /* only consider F-Curves if they're visible (group expanded) */ + if (EXPANDED_AGRP(agrp)) { + rearrange_animchannel_islands(&agrp->channels, rearrange_func, mode, ANIMTYPE_FCURVE); + } + } + } + + /* assemble lists into one list (and clear moved tags) */ + join_groups_action_temp(act); +} + +/* ------------------- */ + +static int animchannels_rearrange_exec(bContext *C, wmOperator *op) +{ + bAnimContext ac; + + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + short mode; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* get mode */ + mode= RNA_enum_get(op->ptr, "direction"); + + /* get animdata blocks */ + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_ANIMDATA); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + for (ale = anim_data.first; ale; ale = ale->next) { + AnimData *adt= ale->data; + + switch (ac.datatype) { + case ANIMCONT_NLA: /* NLA-tracks only */ + rearrange_nla_channels(&ac, adt, mode); + break; + + case ANIMCONT_DRIVERS: /* Drivers list only */ + rearrange_driver_channels(&ac, adt, mode); + break; + + case ANIMCONT_GPENCIL: /* Grease Pencil channels */ + // FIXME: this case probably needs to get moved out of here or treated specially... + printf("grease pencil not supported for moving yet\n"); + break; + + case ANIMCONT_SHAPEKEY: // DOUBLE CHECK ME... + + default: /* some collection of actions */ + // FIXME: actions should only be considered once! + if (adt->action) + rearrange_action_channels(&ac, adt->action, mode); + else if (G.f & G_DEBUG) + printf("animdata has no action\n"); + break; + } + } + + /* free temp data */ + BLI_freelistN(&anim_data); + + /* send notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN|NA_EDITED, NULL); + + return OPERATOR_FINISHED; } -void ANIM_OT_channels_move_bottom (wmOperatorType *ot) +static void ANIM_OT_channels_move (wmOperatorType *ot) { /* identifiers */ - ot->name= "Move Channel(s) to Bottom"; - ot->idname= "ANIM_OT_channels_move_to_bottom"; + ot->name= "Move Channels"; + ot->idname= "ANIM_OT_channels_move"; + ot->description = "Rearrange selected animation channels"; /* api callbacks */ ot->exec= animchannels_rearrange_exec; - ot->poll= ED_operator_areaactive; + ot->poll= animedit_poll_channels_nla_tweakmode_off; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; /* props */ - RNA_def_enum(ot->srna, "direction", NULL /* XXX add enum for this */, REARRANGE_ACTCHAN_BOTTOM, "Direction", ""); + ot->prop= RNA_def_enum(ot->srna, "direction", prop_animchannel_rearrange_types, REARRANGE_ANIMCHAN_DOWN, "Direction", ""); } -#endif // XXX old animation system - needs to be updated for new system... - /* ******************** Delete Channel Operator *********************** */ -static int animchannels_delete_exec(bContext *C, wmOperator *op) +static int animchannels_delete_exec(bContext *C, wmOperator *UNUSED(op)) { bAnimContext ac; ListBase anim_data = {NULL, NULL}; @@ -1004,7 +1170,7 @@ static int animchannels_delete_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void ANIM_OT_channels_delete (wmOperatorType *ot) +static void ANIM_OT_channels_delete (wmOperatorType *ot) { /* identifiers */ ot->name= "Delete Channels"; @@ -1022,7 +1188,7 @@ void ANIM_OT_channels_delete (wmOperatorType *ot) /* ******************** Set Channel Visibility Operator *********************** */ /* NOTE: this operator is only valid in the Graph Editor channels region */ -static int animchannels_visibility_set_exec(bContext *C, wmOperator *op) +static int animchannels_visibility_set_exec(bContext *C, wmOperator *UNUSED(op)) { bAnimContext ac; ListBase anim_data = {NULL, NULL}; @@ -1055,7 +1221,7 @@ static int animchannels_visibility_set_exec(bContext *C, wmOperator *op) BLI_freelistN(&anim_data); /* make all the selected channels visible */ - filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_NODUPLIS); + filter= (ANIMFILTER_SEL | ANIMFILTER_NODUPLIS); ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); for (ale= anim_data.first; ale; ale= ale->next) { @@ -1081,7 +1247,7 @@ static int animchannels_visibility_set_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void ANIM_OT_channels_visibility_set (wmOperatorType *ot) +static void ANIM_OT_channels_visibility_set (wmOperatorType *ot) { /* identifiers */ ot->name= "Set Visibility"; @@ -1090,7 +1256,7 @@ void ANIM_OT_channels_visibility_set (wmOperatorType *ot) /* api callbacks */ ot->exec= animchannels_visibility_set_exec; - ot->poll= ED_operator_ipo_active; + ot->poll= ED_operator_graphedit_active; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -1100,7 +1266,7 @@ void ANIM_OT_channels_visibility_set (wmOperatorType *ot) /* ******************** Toggle Channel Visibility Operator *********************** */ /* NOTE: this operator is only valid in the Graph Editor channels region */ -static int animchannels_visibility_toggle_exec(bContext *C, wmOperator *op) +static int animchannels_visibility_toggle_exec(bContext *C, wmOperator *UNUSED(op)) { bAnimContext ac; ListBase anim_data = {NULL, NULL}; @@ -1154,7 +1320,7 @@ static int animchannels_visibility_toggle_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void ANIM_OT_channels_visibility_toggle (wmOperatorType *ot) +static void ANIM_OT_channels_visibility_toggle (wmOperatorType *ot) { /* identifiers */ ot->name= "Toggle Visibility"; @@ -1163,7 +1329,7 @@ void ANIM_OT_channels_visibility_toggle (wmOperatorType *ot) /* api callbacks */ ot->exec= animchannels_visibility_toggle_exec; - ot->poll= ED_operator_ipo_active; + ot->poll= ED_operator_graphedit_active; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -1172,7 +1338,7 @@ void ANIM_OT_channels_visibility_toggle (wmOperatorType *ot) /* ********************** Set Flags Operator *********************** */ /* defines for setting animation-channel flags */ -EnumPropertyItem prop_animchannel_setflag_types[] = { +static EnumPropertyItem prop_animchannel_setflag_types[] = { {ACHANNEL_SETFLAG_TOGGLE, "TOGGLE", 0, "Toggle", ""}, {ACHANNEL_SETFLAG_CLEAR, "DISABLE", 0, "Disable", ""}, {ACHANNEL_SETFLAG_ADD, "ENABLE", 0, "Enable", ""}, @@ -1182,7 +1348,7 @@ EnumPropertyItem prop_animchannel_setflag_types[] = { /* defines for set animation-channel settings */ // TODO: could add some more types, but those are really quite dependent on the mode... -EnumPropertyItem prop_animchannel_settings_types[] = { +static EnumPropertyItem prop_animchannel_settings_types[] = { {ACHANNEL_SETTING_PROTECT, "PROTECT", 0, "Protect", ""}, {ACHANNEL_SETTING_MUTE, "MUTE", 0, "Mute", ""}, {0, NULL, 0, NULL, NULL} @@ -1286,7 +1452,7 @@ static int animchannels_setflag_exec(bContext *C, wmOperator *op) } -void ANIM_OT_channels_setting_enable (wmOperatorType *ot) +static void ANIM_OT_channels_setting_enable (wmOperatorType *ot) { /* identifiers */ ot->name= "Enable Channel Setting"; @@ -1308,7 +1474,7 @@ void ANIM_OT_channels_setting_enable (wmOperatorType *ot) ot->prop= RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, 0, "Type", ""); } -void ANIM_OT_channels_setting_disable (wmOperatorType *ot) +static void ANIM_OT_channels_setting_disable (wmOperatorType *ot) { /* identifiers */ ot->name= "Disable Channel Setting"; @@ -1330,7 +1496,7 @@ void ANIM_OT_channels_setting_disable (wmOperatorType *ot) ot->prop= RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, 0, "Type", ""); } -void ANIM_OT_channels_setting_invert (wmOperatorType *ot) +static void ANIM_OT_channels_setting_invert (wmOperatorType *ot) { /* identifiers */ ot->name= "Invert Channel Setting"; @@ -1352,7 +1518,7 @@ void ANIM_OT_channels_setting_invert (wmOperatorType *ot) ot->prop= RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, 0, "Type", ""); } -void ANIM_OT_channels_setting_toggle (wmOperatorType *ot) +static void ANIM_OT_channels_setting_toggle (wmOperatorType *ot) { /* identifiers */ ot->name= "Toggle Channel Setting"; @@ -1374,7 +1540,7 @@ void ANIM_OT_channels_setting_toggle (wmOperatorType *ot) ot->prop= RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, 0, "Type", ""); } -void ANIM_OT_channels_editable_toggle (wmOperatorType *ot) +static void ANIM_OT_channels_editable_toggle (wmOperatorType *ot) { /* identifiers */ ot->name= "Toggle Channel Editability"; @@ -1419,7 +1585,7 @@ static int animchannels_expand_exec (bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void ANIM_OT_channels_expand (wmOperatorType *ot) +static void ANIM_OT_channels_expand (wmOperatorType *ot) { /* identifiers */ ot->name= "Expand Channels"; @@ -1461,7 +1627,7 @@ static int animchannels_collapse_exec (bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void ANIM_OT_channels_collapse (wmOperatorType *ot) +static void ANIM_OT_channels_collapse (wmOperatorType *ot) { /* identifiers */ ot->name= "Collapse Channels"; @@ -1479,9 +1645,73 @@ void ANIM_OT_channels_collapse (wmOperatorType *ot) ot->prop= RNA_def_boolean(ot->srna, "all", 1, "All", "Collapse all channels (not just selected ones)"); } +/* ******************* Reenable Disabled Operator ******************* */ + +static int animchannels_enable_poll (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 - Action/Dopesheet/etc. and Graph only */ + if (ELEM(sa->spacetype, SPACE_ACTION, SPACE_IPO) == 0) + return 0; + + return 1; +} + +static int animchannels_enable_exec (bContext *C, wmOperator *UNUSED(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; + + /* filter data */ + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVESONLY | ANIMFILTER_NODUPLIS); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* loop through filtered data and clean curves */ + for (ale= anim_data.first; ale; ale= ale->next) { + FCurve *fcu = (FCurve *)ale->data; + fcu->flag &= ~FCURVE_DISABLED; + } + + /* free temp data */ + BLI_freelistN(&anim_data); + + /* send notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN|NA_EDITED, NULL); + + return OPERATOR_FINISHED; +} + +static void ANIM_OT_channels_fcurves_enable (wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Revive Disabled F-Curves"; + ot->idname= "ANIM_OT_channels_fcurves_enable"; + ot->description= "Clears 'disabled' tag from all F-Curves to get broken F-Curves working again"; + + /* api callbacks */ + ot->exec= animchannels_enable_exec; + ot->poll= animchannels_enable_poll; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + /* ********************** Select All Operator *********************** */ -static int animchannels_deselectall_exec(bContext *C, wmOperator *op) +static int animchannels_deselectall_exec (bContext *C, wmOperator *op) { bAnimContext ac; @@ -1501,7 +1731,7 @@ static int animchannels_deselectall_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void ANIM_OT_channels_select_all_toggle (wmOperatorType *ot) +static void ANIM_OT_channels_select_all_toggle (wmOperatorType *ot) { /* identifiers */ ot->name= "Select All"; @@ -1529,7 +1759,17 @@ static void borderselect_anim_channels (bAnimContext *ac, rcti *rect, short sele View2D *v2d= &ac->ar->v2d; rctf rectf; - float ymin=0, ymax=(float)(-ACHANNEL_HEIGHT); + float ymin, ymax; + + /* set initial y extents */ + if (ac->datatype == ANIMCONT_NLA) { + ymin = (float)(-NLACHANNEL_HEIGHT); + ymax = 0.0f; + } + else { + ymin = 0.0f; + ymax = (float)(-ACHANNEL_HEIGHT); + } /* convert border-region to view coordinates */ UI_view2d_region_to_view(v2d, rect->xmin, rect->ymin+2, &rectf.xmin, &rectf.ymin); @@ -1541,7 +1781,10 @@ static void borderselect_anim_channels (bAnimContext *ac, rcti *rect, short sele /* loop over data, doing border select */ for (ale= anim_data.first; ale; ale= ale->next) { - ymin= ymax - ACHANNEL_STEP; + if (ac->datatype == ANIMCONT_NLA) + ymin= ymax - NLACHANNEL_STEP; + else + ymin= ymax - ACHANNEL_STEP; /* if channel is within border-select region, alter it */ if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))) { @@ -1558,6 +1801,16 @@ static void borderselect_anim_channels (bAnimContext *ac, rcti *rect, short sele agrp->flag &= ~AGRP_ACTIVE; } break; + case ANIMTYPE_NLATRACK: + { + NlaTrack *nlt= (NlaTrack *)ale->data; + + /* for now, it's easier just to do this here manually, as defining a new type + * currently adds complications when doing other stuff + */ + ACHANNEL_SET_FLAG(nlt, selectmode, NLATRACK_SELECTED); + } + break; } } @@ -1603,7 +1856,7 @@ static int animchannels_borderselect_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void ANIM_OT_channels_select_border(wmOperatorType *ot) +static void ANIM_OT_channels_select_border(wmOperatorType *ot) { /* identifiers */ ot->name= "Border Select"; @@ -1627,7 +1880,7 @@ void ANIM_OT_channels_select_border(wmOperatorType *ot) /* ******************** Mouse-Click Operator *********************** */ /* Handle selection changes due to clicking on channels. Settings will get caught by UI code... */ -static int mouse_anim_channels (bAnimContext *ac, float x, int channel_index, short selectmode) +static int mouse_anim_channels (bAnimContext *ac, float UNUSED(x), int channel_index, short selectmode) { ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; @@ -1733,6 +1986,7 @@ static int mouse_anim_channels (bAnimContext *ac, float x, int channel_index, sh case ANIMTYPE_DSMESH: case ANIMTYPE_DSNTREE: case ANIMTYPE_DSTEX: + case ANIMTYPE_DSLAT: { /* sanity checking... */ if (ale->adt) { @@ -1834,7 +2088,9 @@ static int mouse_anim_channels (bAnimContext *ac, float x, int channel_index, sh { bGPdata *gpd= (bGPdata *)ale->data; - /* toggle expand */ + /* toggle expand + * - although the triangle widget already allows this, the whole channel can also be used for this purpose + */ gpd->flag ^= GP_DATA_EXPAND; notifierFlags |= (ND_ANIMCHAN|NA_EDITED); @@ -1842,29 +2098,20 @@ static int mouse_anim_channels (bAnimContext *ac, float x, int channel_index, sh break; case ANIMTYPE_GPLAYER: { -#if 0 // XXX future of this is unclear - bGPdata *gpd= (bGPdata *)ale->owner; // xxx depreceated bGPDlayer *gpl= (bGPDlayer *)ale->data; - if (x >= (ACHANNEL_NAMEWIDTH-16)) { - /* toggle lock */ - gpl->flag ^= GP_LAYER_LOCKED; - } - else if (x >= (ACHANNEL_NAMEWIDTH-32)) { - /* toggle hide */ - gpl->flag ^= GP_LAYER_HIDE; + /* select/deselect */ + if (selectmode == SELECT_INVERT) { + /* invert selection status of this layer only */ + gpl->flag ^= GP_LAYER_SELECT; } - else { - /* select/deselect */ - //if (G.qual & LR_SHIFTKEY) { - //select_gplayer_channel(gpd, gpl, SELECT_INVERT); - //} - //else { - //deselect_gpencil_layers(data, 0); - //select_gplayer_channel(gpd, gpl, SELECT_INVERT); - //} + else { + /* select layer by itself */ + ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR); + gpl->flag |= GP_LAYER_SELECT; } -#endif // XXX future of this is unclear + + notifierFlags |= (ND_ANIMCHAN|NA_EDITED); } break; default: @@ -1885,7 +2132,6 @@ static int mouse_anim_channels (bAnimContext *ac, float x, int channel_index, sh static int animchannels_mouseclick_invoke(bContext *C, wmOperator *op, wmEvent *event) { bAnimContext ac; - Scene *scene; ARegion *ar; View2D *v2d; int mval[2], channel_index; @@ -1899,7 +2145,6 @@ static int animchannels_mouseclick_invoke(bContext *C, wmOperator *op, wmEvent * return OPERATOR_CANCELLED; /* get useful pointers from animation context data */ - scene= ac.scene; ar= ac.ar; v2d= &ar->v2d; @@ -1932,7 +2177,7 @@ static int animchannels_mouseclick_invoke(bContext *C, wmOperator *op, wmEvent * return OPERATOR_FINISHED; } -void ANIM_OT_channels_click (wmOperatorType *ot) +static void ANIM_OT_channels_click (wmOperatorType *ot) { /* identifiers */ ot->name= "Mouse Click on Channels"; @@ -1970,17 +2215,15 @@ void ED_operatortypes_animchannels(void) // XXX does this need to be a separate operator? WM_operatortype_append(ANIM_OT_channels_editable_toggle); - // XXX these need to be updated for new system... todo... - //WM_operatortype_append(ANIM_OT_channels_move_up); - //WM_operatortype_append(ANIM_OT_channels_move_down); - //WM_operatortype_append(ANIM_OT_channels_move_top); - //WM_operatortype_append(ANIM_OT_channels_move_bottom); + WM_operatortype_append(ANIM_OT_channels_move); WM_operatortype_append(ANIM_OT_channels_expand); WM_operatortype_append(ANIM_OT_channels_collapse); WM_operatortype_append(ANIM_OT_channels_visibility_toggle); WM_operatortype_append(ANIM_OT_channels_visibility_set); + + WM_operatortype_append(ANIM_OT_channels_fcurves_enable); } // TODO: check on a poll callback for this, to get hotkeys into menus @@ -2022,11 +2265,11 @@ void ED_keymap_animchannels(wmKeyConfig *keyconf) RNA_boolean_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_expand", PADPLUSKEY, KM_PRESS, KM_CTRL, 0)->ptr, "all", 0); RNA_boolean_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_collapse", PADMINUS, KM_PRESS, KM_CTRL, 0)->ptr, "all", 0); - /* rearranging - actions only */ - //WM_keymap_add_item(keymap, "ANIM_OT_channels_move_up", PAGEUPKEY, KM_PRESS, KM_SHIFT, 0); - //WM_keymap_add_item(keymap, "ANIM_OT_channels_move_down", PAGEDOWNKEY, KM_PRESS, KM_SHIFT, 0); - //WM_keymap_add_item(keymap, "ANIM_OT_channels_move_to_top", PAGEUPKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0); - //WM_keymap_add_item(keymap, "ANIM_OT_channels_move_to_bottom", PAGEDOWNKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0); + /* rearranging */ + RNA_enum_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_move", PAGEUPKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "direction", REARRANGE_ANIMCHAN_UP); + RNA_enum_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_move", PAGEDOWNKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "direction", REARRANGE_ANIMCHAN_DOWN); + RNA_enum_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_move", PAGEUPKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0)->ptr, "direction", REARRANGE_ANIMCHAN_TOP); + RNA_enum_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_move", PAGEDOWNKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0)->ptr, "direction", REARRANGE_ANIMCHAN_BOTTOM); /* Graph Editor only */ WM_keymap_add_item(keymap, "ANIM_OT_channels_visibility_set", VKEY, KM_PRESS, 0, 0); diff --git a/source/blender/editors/animation/anim_deps.c b/source/blender/editors/animation/anim_deps.c index 5312e97c604..be4110c68b9 100644 --- a/source/blender/editors/animation/anim_deps.c +++ b/source/blender/editors/animation/anim_deps.c @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -38,6 +38,7 @@ #include "DNA_sequence_types.h" #include "BLI_blenlib.h" +#include "BLI_utildefines.h" #include "BKE_animsys.h" #include "BKE_action.h" @@ -90,13 +91,13 @@ void ANIM_list_elem_update(Scene *scene, bAnimListElem *ale) else { /* in other case we do standard depsgaph update, ideally we'd be calling property update functions here too ... */ - DAG_id_flush_update(id, OB_RECALC_ALL); // XXX or do we want something more restrictive? + DAG_id_tag_update(id, OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME); // XXX or do we want something more restrictive? } } /* tags the given ID block for refreshes (if applicable) due to * Animation Editor editing */ -void ANIM_id_update(Scene *scene, ID *id) +void ANIM_id_update(Scene *UNUSED(scene), ID *id) { if (id) { AnimData *adt= BKE_animdata_from_id(id); @@ -106,7 +107,7 @@ void ANIM_id_update(Scene *scene, ID *id) adt->recalc |= ADT_RECALC_ANIM; /* set recalc flags */ - DAG_id_flush_update(id, OB_RECALC_ALL); // XXX or do we want something more restrictive? + DAG_id_tag_update(id, OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME); // XXX or do we want something more restrictive? } } @@ -121,7 +122,7 @@ void ANIM_id_update(Scene *scene, ID *id) */ /* perform syncing updates for Action Groups */ -static void animchan_sync_group (bAnimContext *ac, bAnimListElem *ale) +static void animchan_sync_group (bAnimContext *UNUSED(ac), bAnimListElem *ale) { bActionGroup *agrp= (bActionGroup *)ale->data; ID *owner_id= ale->id; @@ -154,7 +155,7 @@ static void animchan_sync_group (bAnimContext *ac, bAnimListElem *ale) } /* perform syncing updates for F-Curves */ -static void animchan_sync_fcurve (bAnimContext *ac, bAnimListElem *ale) +static void animchan_sync_fcurve (bAnimContext *UNUSED(ac), bAnimListElem *ale) { FCurve *fcu= (FCurve *)ale->data; ID *owner_id= ale->id; diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c index b564780f6c0..9b307b92bec 100644 --- a/source/blender/editors/animation/anim_draw.c +++ b/source/blender/editors/animation/anim_draw.c @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -232,7 +232,7 @@ void ANIM_draw_cfra (const bContext *C, View2D *v2d, short flag) /* Draw dark green line if slow-parenting/time-offset is enabled */ if (flag & DRAWCFRA_SHOW_TIMEOFS) { - Object *ob= (scene->basact) ? (scene->basact->object) : 0; + Object *ob= OBACT; if(ob) { float timeoffset= give_timeoffset(ob); // XXX ob->ipoflag is depreceated! @@ -256,7 +256,7 @@ void ANIM_draw_cfra (const bContext *C, View2D *v2d, short flag) /* Draw current frame number in a little box */ if (flag & DRAWCFRA_SHOW_NUMBOX) { - UI_view2d_view_orthoSpecial(C, v2d, 1); + UI_view2d_view_orthoSpecial(CTX_wm_region(C), v2d, 1); draw_cfra_number(scene, v2d, vec[0], (flag & DRAWCFRA_UNIT_SECONDS)); } } @@ -352,14 +352,13 @@ static short bezt_nlamapping_apply(KeyframeEditData *ked, BezTriple *bezt) */ void ANIM_nla_mapping_apply_fcurve (AnimData *adt, FCurve *fcu, short restore, short only_keys) { - KeyframeEditData ked; + KeyframeEditData ked= {{NULL}}; KeyframeEditFunc map_cb; /* init edit data * - AnimData is stored in 'data' * - only_keys is stored in 'i1' */ - memset(&ked, 0, sizeof(KeyframeEditData)); ked.data= (void *)adt; ked.i1= (int)only_keys; @@ -393,7 +392,7 @@ float ANIM_unit_mapping_get_factor (Scene *scene, ID *id, FCurve *fcu, short res if (RNA_SUBTYPE_UNIT(RNA_property_subtype(prop)) == PROP_UNIT_ROTATION) { /* if the radians flag is not set, default to using degrees which need conversions */ - if ((scene) && (scene->unit.flag & USER_UNIT_ROT_RADIANS) == 0) { + if ((scene) && (scene->unit.system_rotation == USER_UNIT_ROT_RADIANS) == 0) { if (restore) return M_PI / 180.0f; /* degrees to radians */ else diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index 0ff75c1cded..dd406acff79 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -69,6 +69,7 @@ #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" +#include "BLI_utildefines.h" #include "BLI_ghash.h" #include "BKE_animsys.h" @@ -78,11 +79,14 @@ #include "BKE_global.h" #include "BKE_group.h" #include "BKE_key.h" +#include "BKE_main.h" #include "BKE_material.h" #include "BKE_node.h" #include "BKE_sequencer.h" +#include "BKE_utildefines.h" #include "ED_anim_api.h" +#include "ED_markers.h" /* ************************************************************ */ /* Blender Context <-> Animation Context mapping */ @@ -91,7 +95,7 @@ /* Get shapekey data being edited (for Action Editor -> ShapeKey mode) */ /* Note: there's a similar function in key.c (ob_get_key) */ -Key *actedit_get_shapekeys (bAnimContext *ac, SpaceAction *saction) +static Key *actedit_get_shapekeys (bAnimContext *ac) { Scene *scene= ac->scene; Object *ob; @@ -105,23 +109,7 @@ Key *actedit_get_shapekeys (bAnimContext *ac, SpaceAction *saction) //if (saction->pin) return NULL; /* shapekey data is stored with geometry data */ - switch (ob->type) { - case OB_MESH: - key= ((Mesh *)ob->data)->key; - break; - - case OB_LATTICE: - key= ((Lattice *)ob->data)->key; - break; - - case OB_CURVE: - case OB_SURF: - key= ((Curve *)ob->data)->key; - break; - - default: - return NULL; - } + key= ob_get_key(ob); if (key) { if (key->type == KEY_RELATIVE) @@ -153,15 +141,17 @@ static short actedit_get_context (bAnimContext *ac, SpaceAction *saction) case SACTCONT_SHAPEKEY: /* 'ShapeKey Editor' */ ac->datatype= ANIMCONT_SHAPEKEY; - ac->data= actedit_get_shapekeys(ac, saction); + ac->data= actedit_get_shapekeys(ac); ac->mode= saction->mode; return 1; case SACTCONT_GPENCIL: /* Grease Pencil */ // XXX review how this mode is handled... - ac->datatype=ANIMCONT_GPENCIL; - //ac->data= CTX_wm_screen(C); // FIXME: add that dopesheet type thing here! - ac->data= NULL; // !!! + /* update scene-pointer (no need to check for pinning yet, as not implemented) */ + saction->ads.source= (ID *)ac->scene; + + ac->datatype= ANIMCONT_GPENCIL; + ac->data= &saction->ads; ac->mode= saction->mode; return 1; @@ -317,7 +307,7 @@ short ANIM_animdata_get_context (const bContext *C, bAnimContext *ac) /* get useful default context settings from context */ ac->scene= scene; if (scene) { - ac->markers= &scene->markers; + ac->markers= ED_context_get_markers(C); ac->obact= (scene->basact)? scene->basact->object : NULL; } ac->sa= sa; @@ -437,7 +427,7 @@ short ANIM_animdata_get_context (const bContext *C, bAnimContext *ac) /* this function allocates memory for a new bAnimListElem struct for the * provided animation channel-data. */ -bAnimListElem *make_new_animlistelem (void *data, short datatype, void *owner, short ownertype, ID *owner_id) +static bAnimListElem *make_new_animlistelem (void *data, short datatype, void *owner, short ownertype, ID *owner_id) { bAnimListElem *ale= NULL; @@ -642,6 +632,19 @@ bAnimListElem *make_new_animlistelem (void *data, short datatype, void *owner, s ale->adt= BKE_animdata_from_id(data); } break; + case ANIMTYPE_DSLAT: + { + Lattice *lt= (Lattice *)data; + AnimData *adt= lt->adt; + + ale->flag= FILTER_LATTICE_OBJD(lt); + + ale->key_data= (adt) ? adt->action : NULL; + ale->datatype= ALE_ACT; + + ale->adt= BKE_animdata_from_id(data); + } + break; case ANIMTYPE_DSSKEY: { Key *key= (Key *)data; @@ -797,7 +800,7 @@ bAnimListElem *make_new_animlistelem (void *data, short datatype, void *owner, s /* ----------------------------------------- */ /* NOTE: when this function returns true, the F-Curve is to be skipped */ -static int skip_fcurve_selected_data(bDopeSheet *ads, FCurve *fcu, ID *owner_id, int filter_mode) +static int skip_fcurve_selected_data (bDopeSheet *ads, FCurve *fcu, ID *owner_id, int filter_mode) { if (GS(owner_id->name) == ID_OB) { Object *ob= (Object *)owner_id; @@ -1065,7 +1068,7 @@ static int animdata_filter_action (bAnimContext *ac, ListBase *anim_data, bDopeS * - 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 (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, AnimData *adt, int filter_mode, void *owner, short ownertype, ID *owner_id) +static int animdata_filter_nla (bAnimContext *UNUSED(ac), ListBase *anim_data, bDopeSheet *UNUSED(ads), AnimData *adt, int filter_mode, void *owner, short ownertype, ID *owner_id) { bAnimListElem *ale; NlaTrack *nlt; @@ -1182,38 +1185,28 @@ static int animdata_filter_shapekey (bAnimContext *ac, ListBase *anim_data, Key return items; } -#if 0 -// FIXME: switch this to use the bDopeSheet... -static int animdata_filter_gpencil (ListBase *anim_data, bScreen *sc, int filter_mode) +/* Grab all Grase Pencil datablocks in file */ +// TODO: should this be amalgamated with the dopesheet filtering code? +static int animdata_filter_gpencil (ListBase *anim_data, void *UNUSED(data), int filter_mode) { bAnimListElem *ale; - ScrArea *sa, *curarea; bGPdata *gpd; bGPDlayer *gpl; int items = 0; /* check if filtering types are appropriate */ + if (!(filter_mode & (ANIMFILTER_ACTGROUPED|ANIMFILTER_CURVESONLY))) { - /* special hack for fullscreen area (which must be this one then): - * - we use the curarea->full as screen to get spaces from, since the - * old (pre-fullscreen) screen was stored there... - * - this is needed as all data would otherwise disappear - */ - // XXX need to get new alternative for curarea - if ((curarea->full) && (curarea->spacetype==SPACE_ACTION)) - sc= curarea->full; - - /* loop over spaces in current screen, finding gpd blocks (could be slow!) */ - for (sa= sc->areabase.first; sa; sa= sa->next) { - /* try to get gp data */ - // XXX need to put back grease pencil api... - gpd= gpencil_data_get_active(sa); - if (gpd == NULL) continue; + /* for now, grab grease pencil datablocks directly from main*/ + for (gpd = G.main->gpencil.first; gpd; gpd = gpd->id.next) { + /* only show if gpd is used by something... */ + if (ID_REAL_USERS(gpd) < 1) + continue; /* add gpd as channel too (if for drawing, and it has layers) */ if ((filter_mode & ANIMFILTER_CHANNELS) && (gpd->layers.first)) { /* add to list */ - ale= make_new_animlistelem(gpd, ANIMTYPE_GPDATABLOCK, sa, ANIMTYPE_SPECIALDATA); + ale= make_new_animlistelem(gpd, ANIMTYPE_GPDATABLOCK, NULL, ANIMTYPE_NONE, NULL); if (ale) { BLI_addtail(anim_data, ale); items++; @@ -1229,7 +1222,7 @@ static int animdata_filter_gpencil (ListBase *anim_data, bScreen *sc, int filter /* only if editable */ if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_GPL(gpl)) { /* add to list */ - ale= make_new_animlistelem(gpl, ANIMTYPE_GPLAYER, gpd, ANIMTYPE_GPDATABLOCK); + ale= make_new_animlistelem(gpl, ANIMTYPE_GPLAYER, gpd, ANIMTYPE_GPDATABLOCK, (ID*)gpd); if (ale) { BLI_addtail(anim_data, ale); items++; @@ -1244,7 +1237,6 @@ static int animdata_filter_gpencil (ListBase *anim_data, bScreen *sc, int filter /* return the number of items added to the list */ return items; } -#endif /* NOTE: owner_id is either material, lamp, or world block, which is the direct owner of the texture stack in question */ static int animdata_filter_dopesheet_texs (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, ID *owner_id, int filter_mode) @@ -1389,15 +1381,35 @@ static int animdata_filter_dopesheet_mats (bAnimContext *ac, ListBase *anim_data 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 (ma == NULL) continue; + /* check if ok */ ANIMDATA_FILTER_CASES(ma, { /* AnimData blocks - do nothing... */ }, ok=1;, ok=1;, ok=1;) + + /* need to check textures */ + if (ok == 0 && !(ads->filterflag & ADS_FILTER_NOTEX)) { + int mtInd; + + for (mtInd=0; mtInd < MAX_MTEX; mtInd++) { + MTex *mtex = ma->mtex[mtInd]; + + if(mtex && mtex->tex) { + ANIMDATA_FILTER_CASES(mtex->tex, + { /* AnimData blocks - do nothing... */ }, + ok=1;, + ok=1;, + ok=1;) + } + + if(ok) + break; + } + } + if (ok == 0) continue; /* make a temp list elem for this */ @@ -1407,7 +1419,6 @@ static int animdata_filter_dopesheet_mats (bAnimContext *ac, ListBase *anim_data } /* if there were no channels found, no need to carry on */ - // XXX: textures with no animated owner material won't work because of this... if (mats.first == NULL) return 0; @@ -1580,6 +1591,14 @@ static int animdata_filter_dopesheet_obdata (bAnimContext *ac, ListBase *anim_da expanded= FILTER_MESH_OBJD(me); } break; + case OB_LATTICE: /* ---- Lattice ---- */ + { + Lattice *lt = (Lattice *)ob->data; + + type= ANIMTYPE_DSLAT; + expanded= FILTER_LATTICE_OBJD(lt); + } + break; } /* special exception for drivers instead of action */ @@ -1838,6 +1857,19 @@ static int animdata_filter_dopesheet_ob (bAnimContext *ac, ListBase *anim_data, } } break; + case OB_LATTICE: /* ------- Lattice ---------- */ + { + Lattice *lt= (Lattice *)ob->data; + + if ((ads->filterflag & ADS_FILTER_NOLAT) == 0) { + ANIMDATA_FILTER_CASES(lt, + { /* AnimData blocks - do nothing... */ }, + obdata_ok= 1;, + obdata_ok= 1;, + obdata_ok= 1;) + } + } + break; } if (obdata_ok) items += animdata_filter_dopesheet_obdata(ac, anim_data, ads, base, filter_mode); @@ -2029,7 +2061,7 @@ static int animdata_filter_dopesheet (bAnimContext *ac, ListBase *anim_data, bDo if ((ads->source == NULL) || (GS(ads->source->name)!=ID_SCE)) { printf("DopeSheet Error: Not scene!\n"); if (G.f & G_DEBUG) - printf("\tPointer = %p, Name = '%s' \n", ads->source, (ads->source)?ads->source->name:NULL); + printf("\tPointer = %p, Name = '%s' \n", (void *)ads->source, (ads->source)?ads->source->name:NULL); return 0; } @@ -2135,7 +2167,7 @@ static int animdata_filter_dopesheet (bAnimContext *ac, ListBase *anim_data, bDo } /* additionally, dopesheet filtering also affects what objects to consider */ - if (ads->filterflag) { + { /* check selection and object type filters */ if ( (ads->filterflag & ADS_FILTER_ONLYSEL) && !((base->flag & SELECT) /*|| (base == sce->basact)*/) ) { /* only selected should be shown */ @@ -2192,7 +2224,7 @@ static int animdata_filter_dopesheet (bAnimContext *ac, ListBase *anim_data, bDo int a; /* firstly check that we actuallly have some materials */ - for (a=0; a < ob->totcol; a++) { + for (a=1; a <= ob->totcol; a++) { Material *ma= give_current_material(ob, a); if (ma) { @@ -2351,6 +2383,23 @@ static int animdata_filter_dopesheet (bAnimContext *ac, ListBase *anim_data, bDo dataOk= !(ads->filterflag & ADS_FILTER_NOMESH);) } break; + case OB_LATTICE: /* ------- Lattice ---------- */ + { + Lattice *lt= (Lattice *)ob->data; + dataOk= 0; + ANIMDATA_FILTER_CASES(lt, + if ((ads->filterflag & ADS_FILTER_NOLAT)==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(lt); + dataOk=0; + }, + dataOk= !(ads->filterflag & ADS_FILTER_NOLAT);, + dataOk= !(ads->filterflag & ADS_FILTER_NOLAT);, + dataOk= !(ads->filterflag & ADS_FILTER_NOLAT);) + } + break; default: /* --- other --- */ dataOk= 0; break; @@ -2385,89 +2434,6 @@ static int animdata_filter_dopesheet (bAnimContext *ac, ListBase *anim_data, bDo if (!actOk && !keyOk && !dataOk && !matOk && !partOk) continue; } - else { - /* check data-types */ - actOk= ANIMDATA_HAS_KEYS(ob); - keyOk= (key != NULL); - - /* materials - only for geometric types */ - matOk= 0; /* by default, not ok... */ - if (ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL) && (ob->totcol)) - { - int a; - - /* firstly check that we actuallly have some materials */ - for (a=0; a < ob->totcol; a++) { - Material *ma= give_current_material(ob, a); - - if ((ma) && ANIMDATA_HAS_KEYS(ma)) { - matOk= 1; - break; - } - } - } - - /* data */ - switch (ob->type) { - case OB_CAMERA: /* ------- Camera ------------ */ - { - Camera *ca= (Camera *)ob->data; - dataOk= ANIMDATA_HAS_KEYS(ca); - } - break; - case OB_LAMP: /* ---------- Lamp ----------- */ - { - Lamp *la= (Lamp *)ob->data; - dataOk= ANIMDATA_HAS_KEYS(la); - } - break; - case OB_CURVE: /* ------- Curve ---------- */ - case OB_SURF: /* ------- Nurbs Surface ---------- */ - case OB_FONT: /* ------- Text Curve ---------- */ - { - Curve *cu= (Curve *)ob->data; - dataOk= ANIMDATA_HAS_KEYS(cu); - } - break; - case OB_MBALL: /* -------- Metas ---------- */ - { - MetaBall *mb= (MetaBall *)ob->data; - dataOk= ANIMDATA_HAS_KEYS(mb); - } - break; - case OB_ARMATURE: /* -------- Armature ---------- */ - { - bArmature *arm= (bArmature *)ob->data; - dataOk= ANIMDATA_HAS_KEYS(arm); - } - break; - case OB_MESH: /* -------- Mesh ---------- */ - { - Mesh *me= (Mesh *)ob->data; - dataOk= ANIMDATA_HAS_KEYS(me); - } - break; - default: /* --- other --- */ - dataOk= 0; - break; - } - - /* particles */ - partOk = 0; - if (ob->particlesystem.first) { - ParticleSystem *psys = ob->particlesystem.first; - for(; psys; psys=psys->next) { - if(psys->part && ANIMDATA_HAS_KEYS(psys->part)) { - partOk = 1; - break; - } - } - } - - /* check if all bad (i.e. nothing to show) */ - if (!actOk && !keyOk && !dataOk && !matOk && !partOk) - continue; - } /* since we're still here, this object should be usable */ items += animdata_filter_dopesheet_ob(ac, anim_data, ads, base, filter_mode); @@ -2501,7 +2467,7 @@ static short animdata_filter_dopesheet_summary (bAnimContext *ac, ListBase *anim /* dopesheet summary * - only for drawing and/or selecting keyframes in channels, but not for real editing - * - only useful for DopeSheet Editor, where the summary is useful + * - only useful for DopeSheet/Action/etc. editors where it is actually useful */ // TODO: we should really check if some other prohibited filters are also active, but that can be for later if ((filter_mode & ANIMFILTER_CHANNELS) && (ads->filterflag & ADS_FILTER_SUMMARY)) { @@ -2602,9 +2568,12 @@ int ANIM_animdata_filter (bAnimContext *ac, ListBase *anim_data, int filter_mode switch (datatype) { case ANIMCONT_ACTION: /* 'Action Editor' */ { + SpaceAction *saction = (SpaceAction *)ac->sa->spacedata.first; + bDopeSheet *ads = (saction)? &saction->ads : NULL; + /* the check for the DopeSheet summary is included here since the summary works here too */ if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items)) - items += animdata_filter_action(ac, anim_data, NULL, data, filter_mode, NULL, ANIMTYPE_NONE, (ID *)obact); + items += animdata_filter_action(ac, anim_data, ads, data, filter_mode, NULL, ANIMTYPE_NONE, (ID *)obact); } break; @@ -2618,7 +2587,7 @@ int ANIM_animdata_filter (bAnimContext *ac, ListBase *anim_data, int filter_mode case ANIMCONT_GPENCIL: { - //items= animdata_filter_gpencil(anim_data, data, filter_mode); + items= animdata_filter_gpencil(anim_data, data, filter_mode); } break; diff --git a/source/blender/editors/animation/anim_intern.h b/source/blender/editors/animation/anim_intern.h index 274d33e4833..4f88f3ed194 100644 --- a/source/blender/editors/animation/anim_intern.h +++ b/source/blender/editors/animation/anim_intern.h @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** diff --git a/source/blender/editors/animation/anim_ipo_utils.c b/source/blender/editors/animation/anim_ipo_utils.c index b71e9ac3507..a9ff27e970a 100644 --- a/source/blender/editors/animation/anim_ipo_utils.c +++ b/source/blender/editors/animation/anim_ipo_utils.c @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -37,13 +37,14 @@ #include "BLI_blenlib.h" #include "BLI_math.h" +#include "BLI_utildefines.h" #include "DNA_anim_types.h" -#include "BKE_utildefines.h" - #include "RNA_access.h" +#include "ED_anim_api.h" + /* ----------------------- Getter functions ----------------------- */ /* Write into "name" buffer, the name of the property (retrieved using RNA from the curve's settings), @@ -74,7 +75,8 @@ int getname_anim_fcurve(char *name, ID *id, FCurve *fcu) /* try to resolve the path */ if (RNA_path_resolve(&id_ptr, fcu->rna_path, &ptr, &prop)) { - char *structname=NULL, *propname=NULL, *arrayname=NULL, arrayindbuf[16]; + char *structname=NULL, *propname=NULL, arrayindbuf[16]; + const char *arrayname=NULL; short free_structname = 0; /* For now, name will consist of 3 parts: struct-name, property name, array index @@ -157,6 +159,9 @@ int getname_anim_fcurve(char *name, ID *id, FCurve *fcu) /* icon for this should be the icon for the base ID */ // TODO: or should we just use the error icon? icon= RNA_struct_ui_icon(id_ptr.type); + + /* tag F-Curve as disabled - as not usable path */ + fcu->flag |= FCURVE_DISABLED; } } @@ -169,14 +174,14 @@ int getname_anim_fcurve(char *name, ID *id, FCurve *fcu) /* step between the major distinguishable color bands of the primary colors */ #define HSV_BANDWIDTH 0.3f -/* used to determine the colour of F-Curves with FCURVE_COLOR_AUTO_RAINBOW set */ +/* used to determine the color of F-Curves with FCURVE_COLOR_AUTO_RAINBOW set */ //void fcurve_rainbow (unsigned int cur, unsigned int tot, float *out) void getcolor_fcurve_rainbow (int cur, int tot, float *out) { float hue, val, sat, fac; int grouping; - /* we try to divide the colours into groupings of n colors, + /* we try to divide the color into groupings of n colors, * where n is: * 3 - for 'odd' numbers of curves - there should be a majority of triplets of curves * 4 - for 'even' numbers of curves - there should be a majority of quartets of curves diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c index 719b46738d3..6aa8e010cc2 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -38,6 +38,7 @@ #include "RNA_enum_types.h" #include "BLI_blenlib.h" +#include "BLI_utildefines.h" #include "BKE_context.h" #include "BKE_fcurve.h" @@ -56,6 +57,7 @@ #include "UI_view2d.h" #include "UI_resources.h" +#include "ED_anim_api.h" #include "ED_markers.h" #include "ED_screen.h" #include "ED_util.h" @@ -65,23 +67,48 @@ /* ************* Marker API **************** */ -static ListBase *context_get_markers(const bContext *C) +/* helper function for getting the list of markers to work on */ +static ListBase *context_get_markers(Scene *scene, ScrArea *sa) { - -#if 0 - /* XXX get them from pose */ - if ((slink->spacetype == SPACE_ACTION) && (saction->flag & SACTION_POSEMARKERS_MOVE)) { - if (saction->action) - markers= &saction->action->markers; - else - markers= NULL; + /* local marker sets... */ + if (sa) { + if (sa->spacetype == SPACE_ACTION) { + SpaceAction *saction = (SpaceAction *)sa->spacedata.first; + + /* local markers can only be shown when there's only a single active action to grab them from + * - flag only takes effect when there's an action, otherwise it can get too confusing? + */ + if (ELEM(saction->mode, SACTCONT_ACTION, SACTCONT_SHAPEKEY) && (saction->action)) + { + if (saction->flag & SACTION_POSEMARKERS_SHOW) + return &saction->action->markers; + } + } } - else -#endif - return &CTX_data_scene(C)->markers; + /* default to using the scene's markers */ + return &scene->markers; +} + +/* ............. */ + +/* public API for getting markers from context */ +ListBase *ED_context_get_markers(const bContext *C) +{ + return context_get_markers(CTX_data_scene(C), CTX_wm_area(C)); +} + +/* public API for getting markers from "animation" context */ +ListBase *ED_animcontext_get_markers(const bAnimContext *ac) +{ + if (ac) + return context_get_markers(ac->scene, ac->sa); + else + return NULL; } +/* --------------------------------- */ + /* Get the marker that is closest to this point */ /* XXX for select, the min_dist should be small */ TimeMarker *ED_markers_find_nearest_marker (ListBase *markers, float x) @@ -175,8 +202,10 @@ void ED_markers_get_minmax (ListBase *markers, short sel, float *first, float *l *last= max; } +/* --------------------------------- */ + /* Adds a marker to list of cfra elems */ -void add_marker_to_cfra_elem(ListBase *lb, TimeMarker *marker, short only_sel) +static void add_marker_to_cfra_elem(ListBase *lb, TimeMarker *marker, short only_sel) { CfraElem *ce, *cen; @@ -218,6 +247,46 @@ void ED_markers_make_cfra_list(ListBase *markers, ListBase *lb, short only_sel) add_marker_to_cfra_elem(lb, marker, only_sel); } +/* --------------------------------- */ + +/* Get the first selected marker */ +TimeMarker *ED_markers_get_first_selected(ListBase *markers) +{ + TimeMarker *marker; + + if (markers) { + for (marker = markers->first; marker; marker = marker->next) { + if (marker->flag & SELECT) + return marker; + } + } + + return NULL; +} + +/* --------------------------------- */ + +/* Print debugging prints of list of markers + * BSI's: do NOT make static or put in if-defs as "unused code". That's too much trouble when we need to use for quick debuggging! + */ +void debug_markers_print_list(ListBase *markers) +{ + TimeMarker *marker; + + if (markers == NULL) { + printf("No markers list to print debug for\n"); + return; + } + + printf("List of markers follows: -----\n"); + + for (marker = markers->first; marker; marker = marker->next) { + printf("\t'%s' on %d at %p with %d\n", marker->name, marker->frame, marker, marker->flag); + } + + printf("End of list ------------------\n"); +} + /* ************* Marker Drawing ************ */ /* function to draw markers */ @@ -239,10 +308,11 @@ static void draw_marker(View2D *v2d, TimeMarker *marker, int cfra, int flag) /* vertical line - dotted */ #ifdef DURIAN_CAMERA_SWITCH - if ((marker->camera) || (flag & DRAW_MARKERS_LINES)) { + if ((marker->camera) || (flag & DRAW_MARKERS_LINES)) #else - if (flag & DRAW_MARKERS_LINES) { + if (flag & DRAW_MARKERS_LINES) #endif + { setlinestyle(3); if (marker->flag & SELECT) @@ -271,7 +341,6 @@ static void draw_marker(View2D *v2d, TimeMarker *marker, int cfra, int flag) UI_icon_draw(xpos*xscale-5.0f, 16.0f, icon_id); - glBlendFunc(GL_ONE, GL_ZERO); glDisable(GL_BLEND); /* and the marker name too, shifted slightly to the top-right */ @@ -313,7 +382,7 @@ static void draw_marker(View2D *v2d, TimeMarker *marker, int cfra, int flag) /* Draw Scene-Markers in time window */ void draw_markers_time(const bContext *C, int flag) { - ListBase *markers= context_get_markers(C); + ListBase *markers= ED_context_get_markers(C); View2D *v2d= UI_view2d_fromcontext(C); TimeMarker *marker; @@ -333,12 +402,103 @@ void draw_markers_time(const bContext *C, int flag) } } +/* ************************ Marker Wrappers API ********************* */ +/* These wrappers allow marker operators to function within the confines + * of standard animation editors, such that they can coexist with the + * primary operations of those editors. + */ + +/* maximum y-axis value (in region screen-space) that marker events should still be accepted for */ +#define ANIMEDIT_MARKER_YAXIS_MAX 40 + +/* ------------------------ */ + +/* special poll() which checks if there are selected markers first */ +static int ed_markers_poll_selected_markers(bContext *C) +{ + ListBase *markers = ED_context_get_markers(C); + + /* first things first: markers can only exist in timeline views */ + if (ED_operator_animview_active(C) == 0) + return 0; + + /* check if some marker is selected */ + return ED_markers_get_first_selected(markers) != NULL; +} + +/* special poll() which checks if there are any markers at all first */ +static int ed_markers_poll_markers_exist(bContext *C) +{ + ListBase *markers = ED_context_get_markers(C); + + /* first things first: markers can only exist in timeline views */ + if (ED_operator_animview_active(C) == 0) + return 0; + + /* list of markers must exist, as well as some markers in it! */ + return (markers && markers->first); +} + +/* ------------------------ */ + +/* Second-tier invoke() callback that performs context validation before running the + * "custom"/third-tier invoke() callback supplied as the last arg (which would normally + * be the operator's invoke() callback elsewhere) + * + * < invoke_func: (fn(bContext*, wmOperator*, wmEvent*)=int) "standard" invoke function + * that operator would otherwise have used. If NULL, the operator's standard + * exec() callback will be called instead in the appropriate places. + */ +static int ed_markers_opwrap_invoke_custom(bContext *C, wmOperator *op, wmEvent *evt, + int (*invoke_func)(bContext*,wmOperator*,wmEvent*)) +{ + ScrArea *sa = CTX_wm_area(C); + int retval = OPERATOR_PASS_THROUGH; + + /* only timeline view doesn't need calling-location validation as it's the only dedicated view */ + if (sa->spacetype != SPACE_TIME) { + /* restrict y-values to within ANIMEDIT_MARKER_YAXIS_MAX of the view's vertical extents, including scrollbars */ + if (evt->mval[1] > ANIMEDIT_MARKER_YAXIS_MAX) { + /* not ok... "pass-through" to let normal editor's operators have a chance at tackling this event... */ + //printf("MARKER-WRAPPER-DEBUG: event mval[1] = %d, so over accepted tolerance\n", evt->mval[1]); + return OPERATOR_CANCELLED|OPERATOR_PASS_THROUGH; + } + } + + /* allow operator to run now */ + if (invoke_func) + retval = invoke_func(C, op, evt); + else if (op->type->exec) + retval = op->type->exec(C, op); + else + BKE_report(op->reports, RPT_ERROR, "Programming error: operator doesn't actually have code to do anything!"); + + /* return status modifications - for now, make this spacetype dependent as above */ + if (sa->spacetype != SPACE_TIME) { + /* unless successful, must add "pass-through" to let normal operator's have a chance at tackling this event */ + if (retval != OPERATOR_FINISHED) + retval |= OPERATOR_PASS_THROUGH; + } + + return retval; +} + +/* standard wrapper - first-tier invoke() callback to be directly assigned to operator typedata + * for operators which don't need any special invoke calls. Any operators with special invoke calls + * though will need to implement their own wrapper which calls the second-tier callback themselves + * (passing through the custom invoke function they use) + */ +static int ed_markers_opwrap_invoke(bContext *C, wmOperator *op, wmEvent *evt) +{ + return ed_markers_opwrap_invoke_custom(C, op, evt, NULL); +} + /* ************************** add markers *************************** */ /* add TimeMarker at curent frame */ -static int ed_marker_add(bContext *C, wmOperator *op) +static int ed_marker_add(bContext *C, wmOperator *UNUSED(op)) { - ListBase *markers= context_get_markers(C); + ListBase *markers= ED_context_get_markers(C); TimeMarker *marker; int frame= CTX_data_scene(C)->r.cfra; @@ -352,16 +512,17 @@ static int ed_marker_add(bContext *C, wmOperator *op) } /* deselect all */ - for(marker= markers->first; marker; marker= marker->next) + for (marker= markers->first; marker; marker= marker->next) marker->flag &= ~SELECT; marker = MEM_callocN(sizeof(TimeMarker), "TimeMarker"); marker->flag= SELECT; marker->frame= frame; - sprintf(marker->name, "F_%02d", frame); // XXX - temp code only + BLI_snprintf(marker->name, sizeof(marker->name), "F_%02d", frame); // XXX - temp code only BLI_addtail(markers, marker); WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL); + WM_event_add_notifier(C, NC_ANIMATION|ND_MARKERS, NULL); return OPERATOR_FINISHED; } @@ -375,7 +536,8 @@ static void MARKER_OT_add(wmOperatorType *ot) /* api callbacks */ ot->exec= ed_marker_add; - ot->poll= ED_operator_areaactive; + ot->invoke = ed_markers_opwrap_invoke; + ot->poll= ED_operator_animview_active; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -395,7 +557,7 @@ functions: exit() cleanup, send notifier - cancel() to escpae from modal + cancel() to escape from modal callbacks: @@ -419,7 +581,7 @@ typedef struct MarkerMove { /* return 0 if not OK */ static int ed_marker_move_init(bContext *C, wmOperator *op) { - ListBase *markers= context_get_markers(C); + ListBase *markers= ED_context_get_markers(C); MarkerMove *mm; TimeMarker *marker; int totmark=0; @@ -487,8 +649,13 @@ static int ed_marker_move_invoke(bContext *C, wmOperator *op, wmEvent *evt) return OPERATOR_CANCELLED; } +static int ed_marker_move_invoke_wrapper(bContext *C, wmOperator *op, wmEvent *evt) +{ + return ed_markers_opwrap_invoke_custom(C, op, evt, ed_marker_move_invoke); +} + /* note, init has to be called succesfully */ -static void ed_marker_move_apply(bContext *C, wmOperator *op) +static void ed_marker_move_apply(wmOperator *op) { MarkerMove *mm= op->customdata; TimeMarker *marker; @@ -507,10 +674,11 @@ static void ed_marker_move_apply(bContext *C, wmOperator *op) static void ed_marker_move_cancel(bContext *C, wmOperator *op) { RNA_int_set(op->ptr, "frames", 0); - ed_marker_move_apply(C, op); + ed_marker_move_apply(op); ed_marker_move_exit(C, op); WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL); + WM_event_add_notifier(C, NC_ANIMATION|ND_MARKERS, NULL); } @@ -534,17 +702,18 @@ static int ed_marker_move_modal(bContext *C, wmOperator *op, wmEvent *evt) case LEFTMOUSE: case MIDDLEMOUSE: case RIGHTMOUSE: - if(WM_modal_tweak_exit(evt, mm->event_type)) { + if (WM_modal_tweak_exit(evt, mm->event_type)) { ed_marker_move_exit(C, op); WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL); + WM_event_add_notifier(C, NC_ANIMATION|ND_MARKERS, NULL); return OPERATOR_FINISHED; } break; case MOUSEMOVE: - if(hasNumInput(&mm->num)) + if (hasNumInput(&mm->num)) break; - + dx= v2d->mask.xmax-v2d->mask.xmin; dx= (v2d->cur.xmax-v2d->cur.xmin)/dx; @@ -558,11 +727,11 @@ static int ed_marker_move_modal(bContext *C, wmOperator *op, wmEvent *evt) if (ELEM(mm->slink->spacetype, SPACE_TIME, SPACE_SOUND)) apply_keyb_grid(evt->shift, evt->ctrl, &fac, 0.0, FPS, 0.1*FPS, 0); else - apply_keyb_grid(evt->shift, evt->ctrl, &fac, 0.0, 1.0, 0.1, U.flag & USER_AUTOGRABGRID); + apply_keyb_grid(evt->shift, evt->ctrl, &fac, 0.0, 1.0, 0.1, 0 /*was: U.flag & USER_AUTOGRABGRID*/); offs= (int)fac; RNA_int_set(op->ptr, "frames", offs); - ed_marker_move_apply(C, op); + ed_marker_move_apply(op); /* cruft below is for header print */ for (a=0, marker= mm->markers->first; marker; marker= marker->next) { @@ -577,19 +746,19 @@ static int ed_marker_move_modal(bContext *C, wmOperator *op, wmEvent *evt) if (ELEM(mm->slink->spacetype, SPACE_TIME, SPACE_SOUND)) { SpaceTime *stime= (SpaceTime *)mm->slink; if (stime->flag & TIME_DRAWFRAMES) - sprintf(str, "Marker %d offset %d", selmarker->frame, offs); + BLI_snprintf(str, sizeof(str), "Marker %d offset %d", selmarker->frame, offs); else - sprintf(str, "Marker %.2f offset %.2f", FRA2TIME(selmarker->frame), FRA2TIME(offs)); + BLI_snprintf(str, sizeof(str), "Marker %.2f offset %.2f", FRA2TIME(selmarker->frame), FRA2TIME(offs)); } else if (mm->slink->spacetype == SPACE_ACTION) { SpaceAction *saction= (SpaceAction *)mm->slink; if (saction->flag & SACTION_DRAWTIME) - sprintf(str, "Marker %.2f offset %.2f", FRA2TIME(selmarker->frame), FRA2TIME(offs)); + BLI_snprintf(str, sizeof(str), "Marker %.2f offset %.2f", FRA2TIME(selmarker->frame), FRA2TIME(offs)); else - sprintf(str, "Marker %.2f offset %.2f", (double)(selmarker->frame), (double)(offs)); + BLI_snprintf(str, sizeof(str), "Marker %.2f offset %.2f", (double)(selmarker->frame), (double)(offs)); } else { - sprintf(str, "Marker %.2f offset %.2f", (double)(selmarker->frame), (double)(offs)); + BLI_snprintf(str, sizeof(str), "Marker %.2f offset %.2f", (double)(selmarker->frame), (double)(offs)); } } else { @@ -597,44 +766,46 @@ static int ed_marker_move_modal(bContext *C, wmOperator *op, wmEvent *evt) if (ELEM(mm->slink->spacetype, SPACE_TIME, SPACE_SOUND)) { SpaceTime *stime= (SpaceTime *)mm->slink; if (stime->flag & TIME_DRAWFRAMES) - sprintf(str, "Marker offset %d ", offs); + BLI_snprintf(str, sizeof(str), "Marker offset %d ", offs); else - sprintf(str, "Marker offset %.2f ", FRA2TIME(offs)); + BLI_snprintf(str, sizeof(str), "Marker offset %.2f ", FRA2TIME(offs)); } else if (mm->slink->spacetype == SPACE_ACTION) { SpaceAction *saction= (SpaceAction *)mm->slink; if (saction->flag & SACTION_DRAWTIME) - sprintf(str, "Marker offset %.2f ", FRA2TIME(offs)); + BLI_snprintf(str, sizeof(str), "Marker offset %.2f ", FRA2TIME(offs)); else - sprintf(str, "Marker offset %.2f ", (double)(offs)); + BLI_snprintf(str, sizeof(str), "Marker offset %.2f ", (double)(offs)); } else { - sprintf(str, "Marker offset %.2f ", (double)(offs)); + BLI_snprintf(str, sizeof(str), "Marker offset %.2f ", (double)(offs)); } } WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL); + WM_event_add_notifier(C, NC_ANIMATION|ND_MARKERS, NULL); ED_area_headerprint(CTX_wm_area(C), str); } } - if(evt->val==KM_PRESS) { + if (evt->val==KM_PRESS) { float vec[3]; char str_tx[256]; - + if (handleNumInput(&mm->num, evt)) { applyNumInput(&mm->num, vec); outputNumInput(&mm->num, str_tx); - + RNA_int_set(op->ptr, "frames", vec[0]); - ed_marker_move_apply(C, op); + ed_marker_move_apply(op); // ed_marker_header_update(C, op, str, (int)vec[0]); // strcat(str, str_tx); - sprintf(str, "Marker offset %s", str_tx); + BLI_snprintf(str, sizeof(str), "Marker offset %s", str_tx); ED_area_headerprint(CTX_wm_area(C), str); - + WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL); + WM_event_add_notifier(C, NC_ANIMATION|ND_MARKERS, NULL); } } @@ -644,7 +815,7 @@ static int ed_marker_move_modal(bContext *C, wmOperator *op, wmEvent *evt) static int ed_marker_move_exec(bContext *C, wmOperator *op) { if(ed_marker_move_init(C, op)) { - ed_marker_move_apply(C, op); + ed_marker_move_apply(op); ed_marker_move_exit(C, op); return OPERATOR_FINISHED; } @@ -660,9 +831,9 @@ static void MARKER_OT_move(wmOperatorType *ot) /* api callbacks */ ot->exec= ed_marker_move_exec; - ot->invoke= ed_marker_move_invoke; + ot->invoke= ed_marker_move_invoke_wrapper; ot->modal= ed_marker_move_modal; - ot->poll= ED_operator_areaactive; + ot->poll= ed_markers_poll_selected_markers; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING|OPTYPE_GRAB_POINTER; @@ -692,9 +863,9 @@ callbacks: /* duplicate selected TimeMarkers */ -static void ed_marker_duplicate_apply(bContext *C, wmOperator *op) +static void ed_marker_duplicate_apply(bContext *C) { - ListBase *markers= context_get_markers(C); + ListBase *markers= ED_context_get_markers(C); TimeMarker *marker, *newmarker; if (markers == NULL) @@ -719,6 +890,7 @@ static void ed_marker_duplicate_apply(bContext *C, wmOperator *op) #endif /* new marker is added to the begining of list */ + // FIXME: bad ordering! BLI_addhead(markers, newmarker); } } @@ -726,7 +898,7 @@ static void ed_marker_duplicate_apply(bContext *C, wmOperator *op) static int ed_marker_duplicate_exec(bContext *C, wmOperator *op) { - ed_marker_duplicate_apply(C, op); + ed_marker_duplicate_apply(C); ed_marker_move_exec(C, op); /* assumes frs delta set */ return OPERATOR_FINISHED; @@ -735,10 +907,15 @@ static int ed_marker_duplicate_exec(bContext *C, wmOperator *op) static int ed_marker_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *evt) { - ed_marker_duplicate_apply(C, op); + ed_marker_duplicate_apply(C); return ed_marker_move_invoke(C, op, evt); } +static int ed_marker_duplicate_invoke_wrapper(bContext *C, wmOperator *op, wmEvent *evt) +{ + return ed_markers_opwrap_invoke_custom(C, op, evt, ed_marker_duplicate_invoke); +} + static void MARKER_OT_duplicate(wmOperatorType *ot) { /* identifiers */ @@ -748,9 +925,9 @@ static void MARKER_OT_duplicate(wmOperatorType *ot) /* api callbacks */ ot->exec= ed_marker_duplicate_exec; - ot->invoke= ed_marker_duplicate_invoke; + ot->invoke= ed_marker_duplicate_invoke_wrapper; ot->modal= ed_marker_move_modal; - ot->poll= ED_operator_areaactive; + ot->poll= ed_markers_poll_selected_markers; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -784,12 +961,12 @@ static void select_timeline_marker_frame(ListBase *markers, int frame, unsigned static int ed_marker_select(bContext *C, wmEvent *evt, int extend, int camera) { - ListBase *markers= context_get_markers(C); + ListBase *markers= ED_context_get_markers(C); View2D *v2d= UI_view2d_fromcontext(C); float viewx; int x, y, cfra; - if(markers == NULL) + if (markers == NULL) return OPERATOR_PASS_THROUGH; x= evt->x - CTX_wm_region(C)->winrct.xmin; @@ -806,27 +983,27 @@ static int ed_marker_select(bContext *C, wmEvent *evt, int extend, int camera) #ifdef DURIAN_CAMERA_SWITCH - if(camera) { + if (camera) { Scene *scene= CTX_data_scene(C); Base *base; TimeMarker *marker; int sel= 0; - + if (!extend) scene_deselect_all(scene); - + for (marker= markers->first; marker; marker= marker->next) { if(marker->frame==cfra) { sel= (marker->flag & SELECT); break; } } - + for (marker= markers->first; marker; marker= marker->next) { - if(marker->camera) { - if(marker->frame==cfra) { + if (marker->camera) { + if (marker->frame==cfra) { base= object_in_scene(marker->camera, scene); - if(base) { + if (base) { ED_base_object_select(base, sel); if(sel) ED_base_object_activate(C, base); @@ -834,15 +1011,16 @@ static int ed_marker_select(bContext *C, wmEvent *evt, int extend, int camera) } } } - + WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, scene); } #endif WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL); + WM_event_add_notifier(C, NC_ANIMATION|ND_MARKERS, NULL); - /* allowing tweaks */ - return OPERATOR_PASS_THROUGH; + /* allowing tweaks, but needs OPERATOR_FINISHED, otherwise renaming fails... [#25987] */ + return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH; } static int ed_marker_select_invoke(bContext *C, wmOperator *op, wmEvent *evt) @@ -855,6 +1033,11 @@ static int ed_marker_select_invoke(bContext *C, wmOperator *op, wmEvent *evt) return ed_marker_select(C, evt, extend, camera); } +static int ed_marker_select_invoke_wrapper(bContext *C, wmOperator *op, wmEvent *evt) +{ + return ed_markers_opwrap_invoke_custom(C, op, evt, ed_marker_select_invoke); +} + static void MARKER_OT_select(wmOperatorType *ot) { /* identifiers */ @@ -863,8 +1046,8 @@ static void MARKER_OT_select(wmOperatorType *ot) ot->idname= "MARKER_OT_select"; /* api callbacks */ - ot->invoke= ed_marker_select_invoke; - ot->poll= ED_operator_areaactive; + ot->invoke= ed_marker_select_invoke_wrapper; + ot->poll= ed_markers_poll_markers_exist; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -899,7 +1082,7 @@ callbacks: static int ed_marker_border_select_exec(bContext *C, wmOperator *op) { View2D *v2d= UI_view2d_fromcontext(C); - ListBase *markers= context_get_markers(C); + ListBase *markers= ED_context_get_markers(C); TimeMarker *marker; float xminf, xmaxf, yminf, ymaxf; int gesture_mode= RNA_int_get(op->ptr, "gesture_mode"); @@ -911,34 +1094,34 @@ static int ed_marker_border_select_exec(bContext *C, wmOperator *op) UI_view2d_region_to_view(v2d, xmin, ymin, &xminf, &yminf); UI_view2d_region_to_view(v2d, xmax, ymax, &xmaxf, &ymaxf); - /* XXX disputable */ - if(yminf > 30.0f || ymaxf < 0.0f) - return 0; - - if(markers == NULL) + if (markers == NULL) return 0; /* XXX marker context */ - for(marker= markers->first; marker; marker= marker->next) { + for (marker= markers->first; marker; marker= marker->next) { if ((marker->frame > xminf) && (marker->frame <= xmaxf)) { switch (gesture_mode) { case GESTURE_MODAL_SELECT: - if ((marker->flag & SELECT) == 0) - marker->flag |= SELECT; + marker->flag |= SELECT; break; case GESTURE_MODAL_DESELECT: - if (marker->flag & SELECT) - marker->flag &= ~SELECT; + marker->flag &= ~SELECT; break; } } } WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL); + WM_event_add_notifier(C, NC_ANIMATION|ND_MARKERS, NULL); return 1; } +static int ed_marker_select_border_invoke_wrapper(bContext *C, wmOperator *op, wmEvent *evt) +{ + return ed_markers_opwrap_invoke_custom(C, op, evt, WM_border_select_invoke); +} + static void MARKER_OT_select_border(wmOperatorType *ot) { /* identifiers */ @@ -948,10 +1131,10 @@ static void MARKER_OT_select_border(wmOperatorType *ot) /* api callbacks */ ot->exec= ed_marker_border_select_exec; - ot->invoke= WM_border_select_invoke; + ot->invoke= ed_marker_select_border_invoke_wrapper; ot->modal= WM_border_select_modal; - ot->poll= ED_operator_areaactive; + ot->poll= ed_markers_poll_markers_exist; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -964,21 +1147,15 @@ static void MARKER_OT_select_border(wmOperatorType *ot) static int ed_marker_select_all_exec(bContext *C, wmOperator *op) { - ListBase *markers= context_get_markers(C); + ListBase *markers= ED_context_get_markers(C); TimeMarker *marker; int action = RNA_enum_get(op->ptr, "action"); - if(markers == NULL) + if (markers == NULL) return OPERATOR_CANCELLED; if (action == SEL_TOGGLE) { - action = SEL_SELECT; - for(marker= markers->first; marker; marker= marker->next) { - if(marker->flag & SELECT) { - action = SEL_DESELECT; - break; - } - } + action = (ED_markers_get_first_selected(markers) != NULL) ? SEL_DESELECT : SEL_SELECT; } for(marker= markers->first; marker; marker= marker->next) { @@ -990,16 +1167,13 @@ static int ed_marker_select_all_exec(bContext *C, wmOperator *op) marker->flag &= ~SELECT; break; case SEL_INVERT: - if (marker->flag & SELECT) { - marker->flag &= ~SELECT; - } else { - marker->flag |= SELECT; - } + marker->flag ^= SELECT; break; } } WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL); + WM_event_add_notifier(C, NC_ANIMATION|ND_MARKERS, NULL); return OPERATOR_FINISHED; } @@ -1013,7 +1187,8 @@ static void MARKER_OT_select_all(wmOperatorType *ot) /* api callbacks */ ot->exec= ed_marker_select_all_exec; - ot->poll= ED_operator_areaactive; + ot->invoke = ed_markers_opwrap_invoke; + ot->poll= ed_markers_poll_markers_exist; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -1022,32 +1197,39 @@ static void MARKER_OT_select_all(wmOperatorType *ot) WM_operator_properties_select_all(ot); } -/* ******************************* remove marker ***************** */ +/* ***************** remove marker *********************** */ /* remove selected TimeMarkers */ -static int ed_marker_delete_exec(bContext *C, wmOperator *op) +static int ed_marker_delete_exec(bContext *C, wmOperator *UNUSED(op)) { - ListBase *markers= context_get_markers(C); + ListBase *markers= ED_context_get_markers(C); TimeMarker *marker, *nmarker; short changed= 0; - if(markers == NULL) + if (markers == NULL) return OPERATOR_CANCELLED; - for(marker= markers->first; marker; marker= nmarker) { + for (marker= markers->first; marker; marker= nmarker) { nmarker= marker->next; - if(marker->flag & SELECT) { + if (marker->flag & SELECT) { BLI_freelinkN(markers, marker); changed= 1; } } - if (changed) + if (changed) { WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL); + WM_event_add_notifier(C, NC_ANIMATION|ND_MARKERS, NULL); + } return OPERATOR_FINISHED; } +static int ed_marker_delete_invoke_wrapper(bContext *C, wmOperator *op, wmEvent *evt) +{ + // XXX: must we keep these confirmations? + return ed_markers_opwrap_invoke_custom(C, op, evt, WM_operator_confirm); +} static void MARKER_OT_delete(wmOperatorType *ot) { @@ -1057,35 +1239,90 @@ static void MARKER_OT_delete(wmOperatorType *ot) ot->idname= "MARKER_OT_delete"; /* api callbacks */ - ot->invoke= WM_operator_confirm; + ot->invoke= ed_marker_delete_invoke_wrapper; ot->exec= ed_marker_delete_exec; - ot->poll= ED_operator_areaactive; + ot->poll= ed_markers_poll_selected_markers; /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + + +/* **************** rename marker ***************** */ + +/* rename first selected TimeMarker */ +static int ed_marker_rename_exec(bContext *C, wmOperator *op) +{ + TimeMarker *marker= ED_markers_get_first_selected(ED_context_get_markers(C)); + + if (marker) { + RNA_string_get(op->ptr, "name", marker->name); + + WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL); + WM_event_add_notifier(C, NC_ANIMATION|ND_MARKERS, NULL); + + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } +} + +static int ed_marker_rename_invoke_wrapper(bContext *C, wmOperator *op, wmEvent *evt) +{ + /* must initialise the marker name first if there is a marker selected */ + TimeMarker *marker = ED_markers_get_first_selected(ED_context_get_markers(C)); + if (marker) + RNA_string_set(op->ptr, "name", marker->name); + /* now see if the operator is usable */ + return ed_markers_opwrap_invoke_custom(C, op, evt, WM_operator_props_popup); } +static void MARKER_OT_rename(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Rename Marker"; + ot->description= "Rename first selected time marker"; + ot->idname= "MARKER_OT_rename"; + + /* api callbacks */ + ot->invoke= ed_marker_rename_invoke_wrapper; + ot->exec= ed_marker_rename_exec; + ot->poll= ed_markers_poll_selected_markers; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* properties */ + ot->prop = RNA_def_string(ot->srna, "name", "RenamedMarker", sizeof(((TimeMarker *)NULL)->name), "Name", "New name for marker"); + //RNA_def_boolean(ot->srna, "ensure_unique", 0, "Ensure Unique", "Ensure that new name is unique within collection of markers"); +} + +/* **************** make links to scene ***************** */ + static int ed_marker_make_links_scene_exec(bContext *C, wmOperator *op) { - ListBase *markers= context_get_markers(C); + ListBase *markers= ED_context_get_markers(C); Scene *scene_to= BLI_findlink(&CTX_data_main(C)->scene, RNA_enum_get(op->ptr, "scene")); TimeMarker *marker, *marker_new; - if(scene_to==NULL) { + if (scene_to==NULL) { BKE_report(op->reports, RPT_ERROR, "Scene not found"); return OPERATOR_CANCELLED; } - if(scene_to == CTX_data_scene(C)) { - BKE_report(op->reports, RPT_ERROR, "Can't link objects into the same scene"); + if (scene_to == CTX_data_scene(C)) { + BKE_report(op->reports, RPT_ERROR, "Can't re-link markers into the same scene"); return OPERATOR_CANCELLED; } /* copy markers */ for (marker= markers->first; marker; marker= marker->next) { - if(marker->flag & SELECT) { + if (marker->flag & SELECT) { marker_new= MEM_dupallocN(marker); + marker_new->prev= marker_new->next = NULL; + BLI_addtail(&scene_to->markers, marker_new); } } @@ -1099,12 +1336,13 @@ static void MARKER_OT_make_links_scene(wmOperatorType *ot) /* identifiers */ ot->name= "Make Links to Scene"; - ot->description= "Link markers to another scene"; + ot->description= "Copy selected markers to another scene"; ot->idname= "MARKER_OT_make_links_scene"; /* api callbacks */ ot->exec= ed_marker_make_links_scene_exec; - ot->poll= ED_operator_areaactive; + ot->invoke = ed_markers_opwrap_invoke; + ot->poll= ed_markers_poll_selected_markers; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -1119,25 +1357,20 @@ static void MARKER_OT_make_links_scene(wmOperatorType *ot) #ifdef DURIAN_CAMERA_SWITCH /* ******************************* camera bind marker ***************** */ -/* remove selected TimeMarkers */ -static int ed_marker_camera_bind_exec(bContext *C, wmOperator *op) +static int ed_marker_camera_bind_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene= CTX_data_scene(C); - ListBase *markers= context_get_markers(C); + ListBase *markers= ED_context_get_markers(C); TimeMarker *marker; - short changed= 0; - if(markers == NULL) + marker= ED_markers_get_first_selected(markers); + if(marker == NULL) return OPERATOR_CANCELLED; - for(marker= markers->first; marker; marker= marker->next) { - if(marker->flag & SELECT) { - marker->camera= scene->camera; - } - } + marker->camera= scene->camera; - if (changed) - WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL); + WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL); + WM_event_add_notifier(C, NC_ANIMATION|ND_MARKERS, NULL); return OPERATOR_FINISHED; } @@ -1151,7 +1384,8 @@ static void MARKER_OT_camera_bind(wmOperatorType *ot) /* api callbacks */ ot->exec= ed_marker_camera_bind_exec; - ot->poll= ED_operator_areaactive; + ot->invoke = ed_markers_opwrap_invoke; + ot->poll= ed_markers_poll_selected_markers; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -1170,6 +1404,7 @@ void ED_operatortypes_marker(void) WM_operatortype_append(MARKER_OT_select_border); WM_operatortype_append(MARKER_OT_select_all); WM_operatortype_append(MARKER_OT_delete); + WM_operatortype_append(MARKER_OT_rename); WM_operatortype_append(MARKER_OT_make_links_scene); #ifdef DURIAN_CAMERA_SWITCH WM_operatortype_append(MARKER_OT_camera_bind); @@ -1201,6 +1436,7 @@ void ED_marker_keymap(wmKeyConfig *keyconf) WM_keymap_verify_item(keymap, "MARKER_OT_select_all", AKEY, KM_PRESS, 0, 0); WM_keymap_verify_item(keymap, "MARKER_OT_delete", XKEY, KM_PRESS, 0, 0); WM_keymap_verify_item(keymap, "MARKER_OT_delete", DELKEY, KM_PRESS, 0, 0); + WM_keymap_verify_item(keymap, "MARKER_OT_rename", MKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "MARKER_OT_move", GKEY, KM_PRESS, 0, 0); #ifdef DURIAN_CAMERA_SWITCH diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c index 9b9c9435518..c08b902a13e 100644 --- a/source/blender/editors/animation/anim_ops.c +++ b/source/blender/editors/animation/anim_ops.c @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -31,6 +31,8 @@ #include "BLO_sys_types.h" +#include "BLI_utildefines.h" + #include "DNA_anim_types.h" #include "DNA_scene_types.h" @@ -45,6 +47,7 @@ #include "WM_api.h" #include "WM_types.h" +#include "ED_anim_api.h" #include "ED_screen.h" #include "anim_intern.h" @@ -151,7 +154,7 @@ static int change_frame_modal(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_RUNNING_MODAL; } -void ANIM_OT_change_frame(wmOperatorType *ot) +static void ANIM_OT_change_frame(wmOperatorType *ot) { /* identifiers */ ot->name= "Change frame"; @@ -206,18 +209,19 @@ static int previewrange_define_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void ANIM_OT_previewrange_set(wmOperatorType *ot) +static void ANIM_OT_previewrange_set(wmOperatorType *ot) { /* identifiers */ ot->name= "Set Preview Range"; ot->idname= "ANIM_OT_previewrange_set"; + ot->description= "Interactively define frame range used for playback"; /* api callbacks */ ot->invoke= WM_border_select_invoke; ot->exec= previewrange_define_exec; ot->modal= WM_border_select_modal; - ot->poll= ED_operator_areaactive; + ot->poll= ED_operator_animview_active; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -233,7 +237,7 @@ void ANIM_OT_previewrange_set(wmOperatorType *ot) /* ****************** clear preview range operator ****************************/ -static int previewrange_clear_exec(bContext *C, wmOperator *op) +static int previewrange_clear_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene= CTX_data_scene(C); ScrArea *curarea= CTX_wm_area(C); @@ -252,16 +256,17 @@ static int previewrange_clear_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void ANIM_OT_previewrange_clear(wmOperatorType *ot) +static void ANIM_OT_previewrange_clear(wmOperatorType *ot) { /* identifiers */ ot->name= "Clear Preview Range"; ot->idname= "ANIM_OT_previewrange_clear"; + ot->description= "Clear Preview Range"; /* api callbacks */ ot->exec= previewrange_clear_exec; - ot->poll= ED_operator_areaactive; + ot->poll= ED_operator_animview_active; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -269,7 +274,7 @@ void ANIM_OT_previewrange_clear(wmOperatorType *ot) /* ****************** time display toggle operator ****************************/ -static int toggle_time_exec(bContext *C, wmOperator *op) +static int toggle_time_exec(bContext *C, wmOperator *UNUSED(op)) { ScrArea *curarea= CTX_wm_area(C); @@ -319,16 +324,17 @@ static int toggle_time_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void ANIM_OT_time_toggle(wmOperatorType *ot) +static void ANIM_OT_time_toggle(wmOperatorType *ot) { /* identifiers */ ot->name= "Toggle Frames/Seconds"; ot->idname= "ANIM_OT_time_toggle"; + ot->description= "Toggle whether timing is displayed in frames or seconds for active timeline view"; /* api callbacks */ ot->exec= toggle_time_exec; - ot->poll= ED_operator_areaactive; + ot->poll= ED_operator_animview_active; } /* ************************** registration **********************************/ diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c index 9edcf637cdc..11795b76905 100644 --- a/source/blender/editors/animation/drivers.c +++ b/source/blender/editors/animation/drivers.c @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -27,18 +27,30 @@ * ***** END GPL LICENSE BLOCK ***** */ +#include <stdio.h> #include <string.h> #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" +#include "BLI_utildefines.h" #include "DNA_anim_types.h" +#include "DNA_object_types.h" +#include "DNA_material_types.h" +#include "DNA_texture_types.h" +#include "DNA_screen_types.h" +#include "DNA_space_types.h" #include "BKE_animsys.h" #include "BKE_depsgraph.h" #include "BKE_fcurve.h" #include "BKE_context.h" +#include "BKE_report.h" +#include "BKE_material.h" +#include "BKE_texture.h" + +#include "ED_keyframing.h" #include "UI_interface.h" @@ -48,6 +60,11 @@ #include "RNA_access.h" #include "RNA_define.h" +#include "anim_intern.h" + +/* called by WM */ +void free_anim_drivers_copybuf (void); + /* ************************************************** */ /* Animation Data Validation */ @@ -58,7 +75,7 @@ * 1 - add new Driver FCurve, * -1 - add new Driver FCurve without driver stuff (for pasting) */ -FCurve *verify_driver_fcurve (ID *id, const char rna_path[], const int array_index, short add) +static FCurve *verify_driver_fcurve (ID *id, const char rna_path[], const int array_index, short add) { AnimData *adt; FCurve *fcu; @@ -115,7 +132,7 @@ FCurve *verify_driver_fcurve (ID *id, const char rna_path[], const int array_ind /* Main Driver Management API calls: * Add a new driver for the specified property on the given ID block */ -short ANIM_add_driver (ID *id, const char rna_path[], int array_index, short flag, int type) +short ANIM_add_driver (ReportList *reports, ID *id, const char rna_path[], int array_index, short flag, int type) { PointerRNA id_ptr, ptr; PropertyRNA *prop; @@ -126,7 +143,9 @@ short ANIM_add_driver (ID *id, const char rna_path[], int array_index, short fla /* validate pointer first - exit if failure */ RNA_id_pointer_create(id, &id_ptr); if ((RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop) == 0) || (prop == NULL)) { - printf("Add Driver: Could not add Driver, as RNA Path is invalid for the given ID (ID = %s, Path = %s)\n", id->name, rna_path); + BKE_reportf(reports, RPT_ERROR, + "Could not add Driver, as RNA Path is invalid for the given ID (ID = %s, Path = %s)", + id->name, rna_path); return 0; } @@ -153,7 +172,10 @@ short ANIM_add_driver (ID *id, const char rna_path[], int array_index, short fla /* set the type of the driver */ driver->type= type; - /* fill in current value for python */ + /* creating drivers for buttons will create the driver(s) with type + * "scripted expression" so that their values won't be lost immediately, + * so here we copy those values over to the driver's expression + */ if (type == DRIVER_TYPE_PYTHON) { PropertyType proptype= RNA_property_type(prop); int array= RNA_property_array_length(&ptr, prop); @@ -180,6 +202,17 @@ short ANIM_add_driver (ID *id, const char rna_path[], int array_index, short fla BLI_snprintf(expression, maxlen, "%.3f", fval); } } + + /* for easier setup of drivers from UI, a driver variable should be + * added if flag is set (UI calls only) + */ + if (flag & CREATEDRIVER_WITH_DEFAULT_DVAR) { + /* assume that users will mostly want this to be of type "Transform Channel" too, + * since this allows the easiest setting up of common rig components + */ + DriverVar *dvar = driver_add_new_variable(driver); + driver_change_variable_type(dvar, DVAR_TYPE_TRANSFORM_CHAN); + } } /* set the done status */ @@ -193,23 +226,21 @@ short ANIM_add_driver (ID *id, const char rna_path[], int array_index, short fla /* Main Driver Management API calls: * Remove the driver for the specified property on the given ID block (if available) */ -short ANIM_remove_driver (struct ID *id, const char rna_path[], int array_index, short flag) +short ANIM_remove_driver (ReportList *UNUSED(reports), ID *id, const char rna_path[], int array_index, short UNUSED(flag)) { AnimData *adt; FCurve *fcu; int success= 0; - /* get F-Curve - * Note: here is one of the places where we don't want new F-Curve + Driver added! - * so 'add' var must be 0 - */ /* we don't check the validity of the path here yet, but it should be ok... */ adt= BKE_animdata_from_id(id); - if(adt) { - if(array_index == -1) { + if (adt) { + if (array_index == -1) { + /* step through all drivers, removing all of those with the same base path */ FCurve *fcu_iter= adt->drivers.first; - while((fcu= iter_step_fcurve(fcu_iter, rna_path))) { + + while ((fcu = iter_step_fcurve(fcu_iter, rna_path)) != NULL) { /* store the next fcurve for looping */ fcu_iter= fcu->next; @@ -222,8 +253,12 @@ short ANIM_remove_driver (struct ID *id, const char rna_path[], int array_index, } } else { + /* find the matching driver and remove it only + * Note: here is one of the places where we don't want new F-Curve + Driver added! + * so 'add' var must be 0 + */ fcu= verify_driver_fcurve(id, rna_path, array_index, 0); - if(fcu) { + if (fcu) { BLI_remlink(&adt->drivers, fcu); free_fcurve(fcu); @@ -262,7 +297,7 @@ short ANIM_driver_can_paste (void) /* Main Driver Management API calls: * Make a copy of the driver for the specified property on the given ID block */ -short ANIM_copy_driver (ID *id, const char rna_path[], int array_index, short flag) +short ANIM_copy_driver (ReportList *reports, ID *id, const char rna_path[], int array_index, short UNUSED(flag)) { PointerRNA id_ptr, ptr; PropertyRNA *prop; @@ -271,7 +306,9 @@ short ANIM_copy_driver (ID *id, const char rna_path[], int array_index, short fl /* validate pointer first - exit if failure */ RNA_id_pointer_create(id, &id_ptr); if ((RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop) == 0) || (prop == NULL)) { - printf("Copy Driver: Could not find Driver, as RNA Path is invalid for the given ID (ID = %s, Path = %s)\n", id->name, rna_path); + BKE_reportf(reports, RPT_ERROR, + "Could not find Driver to copy, as RNA Path is invalid for the given ID (ID = %s, Path = %s)", + id->name, rna_path); return 0; } @@ -307,7 +344,7 @@ short ANIM_copy_driver (ID *id, const char rna_path[], int array_index, short fl * Add a new driver for the specified property on the given ID block or replace an existing one * with the driver + driver-curve data from the buffer */ -short ANIM_paste_driver (ID *id, const char rna_path[], int array_index, short flag) +short ANIM_paste_driver (ReportList *reports, ID *id, const char rna_path[], int array_index, short UNUSED(flag)) { PointerRNA id_ptr, ptr; PropertyRNA *prop; @@ -316,13 +353,15 @@ short ANIM_paste_driver (ID *id, const char rna_path[], int array_index, short f /* validate pointer first - exit if failure */ RNA_id_pointer_create(id, &id_ptr); if ((RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop) == 0) || (prop == NULL)) { - printf("Paste Driver: Could not add Driver, as RNA Path is invalid for the given ID (ID = %s, Path = %s)\n", id->name, rna_path); + BKE_reportf(reports, RPT_ERROR, + "Could not paste Driver, as RNA Path is invalid for the given ID (ID = %s, Path = %s)", + id->name, rna_path); return 0; } /* if the buffer is empty, cannot paste... */ if (channeldriver_copypaste_buf == NULL) { - printf("Paste Driver: No Driver to paste. \n"); + BKE_report(reports, RPT_ERROR, "Paste Driver: No Driver to paste."); return 0; } @@ -360,28 +399,104 @@ short ANIM_paste_driver (ID *id, const char rna_path[], int array_index, short f /* ************************************************** */ /* UI-Button Interface */ +/* Temporary wrapper for driver operators for buttons to make it easier to create + * such drivers by rerouting all paths through the active object instead so that + * they will get picked up by the dependency system. + * + * < C: context pointer - for getting active data + * <> ptr: RNA pointer for property's datablock. May be modified as result of path remapping. + * < prop: RNA definition of property to add for + * + * > returns: MEM_alloc'd string representing the path to the property from the given PointerRNA + */ +static char *get_driver_path_hack (bContext *C, PointerRNA *ptr, PropertyRNA *prop) +{ + ID *id = (ID *)ptr->id.data; + ScrArea *sa = CTX_wm_area(C); + + /* get standard path which may be extended */ + char *basepath = RNA_path_from_ID_to_property(ptr, prop); + char *path = basepath; /* in case no remapping is needed */ + + /* Remapping will only be performed in the Properties Editor, as only this + * restricts the subspace of options to the 'active' data (a manageable state) + */ + // TODO: watch out for pinned context? + if ((sa) && (sa->spacetype == SPACE_BUTS)) { + Object *ob = CTX_data_active_object(C); + + if (ob && id) { + /* only id-types which can be remapped to go through objects should be considered */ + switch (GS(id->name)) { + case ID_MA: /* materials */ + { + Material *ma = give_current_material(ob, ob->actcol); + + /* assumes: material will only be shown if it is active objects's active material it's ok */ + if ((ID*)ma == id) { + /* create new path */ + // TODO: use RNA path functions to construct instead? + path = BLI_sprintfN("material_slots[\"%s\"].material.%s", + ma->id.name+2, basepath); + + /* free old one */ + MEM_freeN(basepath); + } + } + break; + + case ID_TE: /* textures */ + { + Material *ma = give_current_material(ob, ob->actcol); + Tex *tex = give_current_material_texture(ma); + + /* assumes: texture will only be shown if it is active material's active texture it's ok */ + if ((ID*)tex == id) { + /* create new path */ + // TODO: use RNA path functions to construct step by step instead? + path = BLI_sprintfN("material_slots[\"%s\"].material.texture_slots[\"%s\"].texture.%s", + ma->id.name+2, tex->id.name+2, basepath); + + /* free old one */ + MEM_freeN(basepath); + } + } + break; + } + + /* fix RNA pointer, as we've now changed the ID root by changing the paths */ + if (basepath != path) { + /* rebase provided pointer so that it starts from object... */ + RNA_pointer_create(&ob->id, ptr->type, ptr->data, ptr); + } + } + } + + /* the path should now have been corrected for use */ + return path; +} + /* Add Driver Button Operator ------------------------ */ static int add_driver_button_exec (bContext *C, wmOperator *op) { - PointerRNA ptr; + PointerRNA ptr= {{NULL}}; PropertyRNA *prop= NULL; - char *path; short success= 0; int index, all= RNA_boolean_get(op->ptr, "all"); /* try to create driver using property retrieved from UI */ - memset(&ptr, 0, sizeof(PointerRNA)); - uiAnimContextProperty(C, &ptr, &prop, &index); - + uiContextActiveProperty(C, &ptr, &prop, &index); + if (all) index= -1; - - if (ptr.data && prop && RNA_property_animateable(&ptr, prop)) { - path= RNA_path_from_ID_to_property(&ptr, prop); + + if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) { + char *path= get_driver_path_hack(C, &ptr, prop); + short flags = CREATEDRIVER_WITH_DEFAULT_DVAR; if (path) { - success+= ANIM_add_driver(ptr.id.data, path, index, 0, DRIVER_TYPE_PYTHON); + success+= ANIM_add_driver(op->reports, ptr.id.data, path, index, flags, DRIVER_TYPE_PYTHON); MEM_freeN(path); } @@ -389,6 +504,8 @@ static int add_driver_button_exec (bContext *C, wmOperator *op) if (success) { /* send updates */ + uiContextAnimUpdate(C); + DAG_ids_flush_update(CTX_data_main(C), 0); WM_event_add_notifier(C, NC_ANIMATION|ND_FCURVES_ORDER, NULL); // XXX @@ -419,27 +536,28 @@ void ANIM_OT_driver_button_add (wmOperatorType *ot) static int remove_driver_button_exec (bContext *C, wmOperator *op) { - PointerRNA ptr; + PointerRNA ptr= {{NULL}}; PropertyRNA *prop= NULL; - char *path; short success= 0; int index, all= RNA_boolean_get(op->ptr, "all"); /* try to find driver using property retrieved from UI */ - memset(&ptr, 0, sizeof(PointerRNA)); - uiAnimContextProperty(C, &ptr, &prop, &index); + uiContextActiveProperty(C, &ptr, &prop, &index); if (all) index= -1; - - if (ptr.data && prop) { - path= RNA_path_from_ID_to_property(&ptr, prop); - success= ANIM_remove_driver(ptr.id.data, path, index, 0); + + if (ptr.id.data && ptr.data && prop) { + char *path= get_driver_path_hack(C, &ptr, prop); + + success= ANIM_remove_driver(op->reports, ptr.id.data, path, index, 0); MEM_freeN(path); } if (success) { /* send updates */ + uiContextAnimUpdate(C); + DAG_ids_flush_update(CTX_data_main(C), 0); WM_event_add_notifier(C, NC_ANIMATION|ND_FCURVES_ORDER, NULL); // XXX @@ -470,22 +588,22 @@ void ANIM_OT_driver_button_remove (wmOperatorType *ot) static int copy_driver_button_exec (bContext *C, wmOperator *op) { - PointerRNA ptr; + PointerRNA ptr= {{NULL}}; PropertyRNA *prop= NULL; - char *path; short success= 0; int index; /* try to create driver using property retrieved from UI */ - memset(&ptr, 0, sizeof(PointerRNA)); - uiAnimContextProperty(C, &ptr, &prop, &index); + uiContextActiveProperty(C, &ptr, &prop, &index); - if (ptr.data && prop && RNA_property_animateable(&ptr, prop)) { - path= RNA_path_from_ID_to_property(&ptr, prop); + if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) { + char *path= get_driver_path_hack(C, &ptr, prop); if (path) { /* only copy the driver for the button that this was involved for */ - success= ANIM_copy_driver(ptr.id.data, path, index, 0); + success= ANIM_copy_driver(op->reports, ptr.id.data, path, index, 0); + + uiContextAnimUpdate(C); MEM_freeN(path); } @@ -514,22 +632,22 @@ void ANIM_OT_copy_driver_button (wmOperatorType *ot) static int paste_driver_button_exec (bContext *C, wmOperator *op) { - PointerRNA ptr; + PointerRNA ptr= {{NULL}}; PropertyRNA *prop= NULL; - char *path; short success= 0; int index; /* try to create driver using property retrieved from UI */ - memset(&ptr, 0, sizeof(PointerRNA)); - uiAnimContextProperty(C, &ptr, &prop, &index); + uiContextActiveProperty(C, &ptr, &prop, &index); - if (ptr.data && prop && RNA_property_animateable(&ptr, prop)) { - path= RNA_path_from_ID_to_property(&ptr, prop); + if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) { + char *path= get_driver_path_hack(C, &ptr, prop); if (path) { /* only copy the driver for the button that this was involved for */ - success= ANIM_paste_driver(ptr.id.data, path, index, 0); + success= ANIM_paste_driver(op->reports, ptr.id.data, path, index, 0); + + uiContextAnimUpdate(C); MEM_freeN(path); } diff --git a/source/blender/editors/animation/fmodifier_ui.c b/source/blender/editors/animation/fmodifier_ui.c index 35e6cb66d45..0b8619c1f6e 100644 --- a/source/blender/editors/animation/fmodifier_ui.c +++ b/source/blender/editors/animation/fmodifier_ui.c @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -43,6 +43,7 @@ #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" +#include "BLI_utildefines.h" #include "BKE_context.h" #include "BKE_fcurve.h" @@ -52,10 +53,11 @@ #include "RNA_access.h" - #include "UI_interface.h" #include "UI_resources.h" +#include "ED_anim_api.h" + /* ********************************************** */ /* UI STUFF */ @@ -74,7 +76,7 @@ } /* callback to verify modifier data */ -static void validate_fmodifier_cb (bContext *C, void *fcm_v, void *dummy) +static void validate_fmodifier_cb (bContext *UNUSED(C), void *fcm_v, void *UNUSED(arg)) { FModifier *fcm= (FModifier *)fcm_v; FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); @@ -215,7 +217,7 @@ static void draw_modifier__generator(uiLayout *layout, ID *id, FModifier *fcm, s /* --------------- */ /* draw settings for generator modifier */ -static void draw_modifier__fn_generator(uiLayout *layout, ID *id, FModifier *fcm, short width) +static void draw_modifier__fn_generator(uiLayout *layout, ID *id, FModifier *fcm, short UNUSED(width)) { uiLayout *col; PointerRNA ptr; @@ -225,20 +227,20 @@ static void draw_modifier__fn_generator(uiLayout *layout, ID *id, FModifier *fcm /* add the settings */ col= uiLayoutColumn(layout, 1); - uiItemR(col, &ptr, "function_type", 0, "", 0); - uiItemR(col, &ptr, "use_additive", UI_ITEM_R_TOGGLE, NULL, 0); + uiItemR(col, &ptr, "function_type", 0, "", ICON_NULL); + uiItemR(col, &ptr, "use_additive", UI_ITEM_R_TOGGLE, NULL, ICON_NULL); col= uiLayoutColumn(layout, 0); // no grouping for now - uiItemR(col, &ptr, "amplitude", 0, NULL, 0); - uiItemR(col, &ptr, "phase_multiplier", 0, NULL, 0); - uiItemR(col, &ptr, "phase_offset", 0, NULL, 0); - uiItemR(col, &ptr, "value_offset", 0, NULL, 0); + uiItemR(col, &ptr, "amplitude", 0, NULL, ICON_NULL); + uiItemR(col, &ptr, "phase_multiplier", 0, NULL, ICON_NULL); + uiItemR(col, &ptr, "phase_offset", 0, NULL, ICON_NULL); + uiItemR(col, &ptr, "value_offset", 0, NULL, ICON_NULL); } /* --------------- */ /* draw settings for cycles modifier */ -static void draw_modifier__cycles(uiLayout *layout, ID *id, FModifier *fcm, short width) +static void draw_modifier__cycles(uiLayout *layout, ID *id, FModifier *fcm, short UNUSED(width)) { uiLayout *split, *col; PointerRNA ptr; @@ -253,21 +255,21 @@ static void draw_modifier__cycles(uiLayout *layout, ID *id, FModifier *fcm, shor /* before range */ col= uiLayoutColumn(split, 1); - uiItemL(col, "Before:", 0); - uiItemR(col, &ptr, "mode_before", 0, "", 0); - uiItemR(col, &ptr, "cycles_before", 0, NULL, 0); + uiItemL(col, "Before:", ICON_NULL); + uiItemR(col, &ptr, "mode_before", 0, "", ICON_NULL); + uiItemR(col, &ptr, "cycles_before", 0, NULL, ICON_NULL); /* after range */ col= uiLayoutColumn(split, 1); - uiItemL(col, "After:", 0); - uiItemR(col, &ptr, "mode_after", 0, "", 0); - uiItemR(col, &ptr, "cycles_after", 0, NULL, 0); + uiItemL(col, "After:", ICON_NULL); + uiItemR(col, &ptr, "mode_after", 0, "", ICON_NULL); + uiItemR(col, &ptr, "cycles_after", 0, NULL, ICON_NULL); } /* --------------- */ /* draw settings for noise modifier */ -static void draw_modifier__noise(uiLayout *layout, ID *id, FModifier *fcm, short width) +static void draw_modifier__noise(uiLayout *layout, ID *id, FModifier *fcm, short UNUSED(width)) { uiLayout *split, *col; PointerRNA ptr; @@ -276,20 +278,20 @@ static void draw_modifier__noise(uiLayout *layout, ID *id, FModifier *fcm, short RNA_pointer_create(id, &RNA_FModifierNoise, fcm, &ptr); /* blending mode */ - uiItemR(layout, &ptr, "blend_type", 0, NULL, 0); + uiItemR(layout, &ptr, "blend_type", 0, NULL, ICON_NULL); /* split into 2 columns */ split= uiLayoutSplit(layout, 0.5f, 0); /* col 1 */ col= uiLayoutColumn(split, 0); - uiItemR(col, &ptr, "scale", 0, NULL, 0); - uiItemR(col, &ptr, "strength", 0, NULL, 0); + uiItemR(col, &ptr, "scale", 0, NULL, ICON_NULL); + uiItemR(col, &ptr, "strength", 0, NULL, ICON_NULL); /* col 2 */ col= uiLayoutColumn(split, 0); - uiItemR(col, &ptr, "phase", 0, NULL, 0); - uiItemR(col, &ptr, "depth", 0, NULL, 0); + uiItemR(col, &ptr, "phase", 0, NULL, ICON_NULL); + uiItemR(col, &ptr, "depth", 0, NULL, ICON_NULL); } /* --------------- */ @@ -374,7 +376,7 @@ static int binarysearch_fcm_envelopedata_index (FCM_EnvelopeData array[], float /* 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) +static void fmod_envelope_addpoint_cb (bContext *C, void *fcm_dv, void *UNUSED(arg)) { Scene *scene= CTX_data_scene(C); FMod_Envelope *env= (FMod_Envelope *)fcm_dv; @@ -426,7 +428,7 @@ static void fmod_envelope_addpoint_cb (bContext *C, void *fcm_dv, void *dummy) /* 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) +static void fmod_envelope_deletepoint_cb (bContext *UNUSED(C), void *fcm_dv, void *ind_v) { FMod_Envelope *env= (FMod_Envelope *)fcm_dv; FCM_EnvelopeData *fedn; @@ -454,7 +456,7 @@ static void fmod_envelope_deletepoint_cb (bContext *C, void *fcm_dv, void *ind_v } /* draw settings for envelope modifier */ -static void draw_modifier__envelope(uiLayout *layout, ID *id, FModifier *fcm, short width) +static void draw_modifier__envelope(uiLayout *layout, ID *id, FModifier *fcm, short UNUSED(width)) { FMod_Envelope *env= (FMod_Envelope *)fcm->data; FCM_EnvelopeData *fed; @@ -469,12 +471,12 @@ static void draw_modifier__envelope(uiLayout *layout, ID *id, FModifier *fcm, sh /* general settings */ col= uiLayoutColumn(layout, 1); - uiItemL(col, "Envelope:", 0); - uiItemR(col, &ptr, "reference_value", 0, NULL, 0); + uiItemL(col, "Envelope:", ICON_NULL); + uiItemR(col, &ptr, "reference_value", 0, NULL, ICON_NULL); row= uiLayoutRow(col, 1); - uiItemR(row, &ptr, "default_min", 0, "Min", 0); - uiItemR(row, &ptr, "default_max", 0, "Max", 0); + uiItemR(row, &ptr, "default_min", 0, "Min", ICON_NULL); + uiItemR(row, &ptr, "default_max", 0, "Max", ICON_NULL); /* control points header */ // TODO: move this control-point control stuff to using the new special widgets for lists @@ -509,7 +511,7 @@ static void draw_modifier__envelope(uiLayout *layout, ID *id, FModifier *fcm, sh /* --------------- */ /* draw settings for limits modifier */ -static void draw_modifier__limits(uiLayout *layout, ID *id, FModifier *fcm, short width) +static void draw_modifier__limits(uiLayout *layout, ID *id, FModifier *fcm, short UNUSED(width)) { uiLayout *split, *col, *row; PointerRNA ptr; @@ -526,13 +528,13 @@ static void draw_modifier__limits(uiLayout *layout, ID *id, FModifier *fcm, shor /* x-minimum */ col= uiLayoutColumn(split, 1); - uiItemR(col, &ptr, "use_min_x", 0, NULL, 0); - uiItemR(col, &ptr, "min_x", 0, NULL, 0); + uiItemR(col, &ptr, "use_min_x", 0, NULL, ICON_NULL); + uiItemR(col, &ptr, "min_x", 0, NULL, ICON_NULL); /* y-minimum*/ col= uiLayoutColumn(split, 1); - uiItemR(col, &ptr, "use_min_y", 0, NULL, 0); - uiItemR(col, &ptr, "min_y", 0, NULL, 0); + uiItemR(col, &ptr, "use_min_y", 0, NULL, ICON_NULL); + uiItemR(col, &ptr, "min_y", 0, NULL, ICON_NULL); } /* row 2: maximum */ @@ -544,20 +546,20 @@ static void draw_modifier__limits(uiLayout *layout, ID *id, FModifier *fcm, shor /* x-minimum */ col= uiLayoutColumn(split, 1); - uiItemR(col, &ptr, "use_max_x", 0, NULL, 0); - uiItemR(col, &ptr, "max_x", 0, NULL, 0); + uiItemR(col, &ptr, "use_max_x", 0, NULL, ICON_NULL); + uiItemR(col, &ptr, "max_x", 0, NULL, ICON_NULL); /* y-minimum*/ col= uiLayoutColumn(split, 1); - uiItemR(col, &ptr, "use_max_y", 0, NULL, 0); - uiItemR(col, &ptr, "max_y", 0, NULL, 0); + uiItemR(col, &ptr, "use_max_y", 0, NULL, ICON_NULL); + uiItemR(col, &ptr, "max_y", 0, NULL, ICON_NULL); } } /* --------------- */ /* draw settings for stepped interpolation modifier */ -static void draw_modifier__stepped(uiLayout *layout, ID *id, FModifier *fcm, short width) +static void draw_modifier__stepped(uiLayout *layout, ID *id, FModifier *fcm, short UNUSED(width)) { uiLayout *col, *subcol; PointerRNA ptr; @@ -567,24 +569,24 @@ static void draw_modifier__stepped(uiLayout *layout, ID *id, FModifier *fcm, sho /* block 1: "stepping" settings */ col= uiLayoutColumn(layout, 0); - uiItemR(col, &ptr, "frame_step", 0, NULL, 0); - uiItemR(col, &ptr, "frame_offset", 0, NULL, 0); + uiItemR(col, &ptr, "frame_step", 0, NULL, ICON_NULL); + uiItemR(col, &ptr, "frame_offset", 0, NULL, ICON_NULL); /* block 2: start range settings */ col= uiLayoutColumn(layout, 1); - uiItemR(col, &ptr, "use_frame_start", 0, NULL, 0); + uiItemR(col, &ptr, "use_frame_start", 0, NULL, ICON_NULL); subcol = uiLayoutColumn(col, 1); uiLayoutSetActive(subcol, RNA_boolean_get(&ptr, "use_frame_start")); - uiItemR(subcol, &ptr, "frame_start", 0, NULL, 0); + uiItemR(subcol, &ptr, "frame_start", 0, NULL, ICON_NULL); /* block 3: end range settings */ col= uiLayoutColumn(layout, 1); - uiItemR(col, &ptr, "use_frame_end", 0, NULL, 0); + uiItemR(col, &ptr, "use_frame_end", 0, NULL, ICON_NULL); subcol = uiLayoutColumn(col, 1); uiLayoutSetActive(subcol, RNA_boolean_get(&ptr, "use_frame_end")); - uiItemR(subcol, &ptr, "frame_end", 0, NULL, 0); + uiItemR(subcol, &ptr, "frame_end", 0, NULL, ICON_NULL); } /* --------------- */ @@ -616,16 +618,16 @@ void ANIM_uiTemplate_fmodifier_draw (uiLayout *layout, ID *id, ListBase *modifie uiBlockSetEmboss(block, UI_EMBOSSN); /* expand */ - uiItemR(subrow, &ptr, "show_expanded", UI_ITEM_R_ICON_ONLY, "", 0); + uiItemR(subrow, &ptr, "show_expanded", UI_ITEM_R_ICON_ONLY, "", ICON_NULL); /* checkbox for 'active' status (for now) */ - uiItemR(subrow, &ptr, "active", UI_ITEM_R_ICON_ONLY, "", 0); + uiItemR(subrow, &ptr, "active", UI_ITEM_R_ICON_ONLY, "", ICON_NULL); /* name */ if (fmi) - uiItemL(subrow, fmi->name, 0); + uiItemL(subrow, fmi->name, ICON_NULL); else - uiItemL(subrow, "<Unknown Modifier>", 0); + uiItemL(subrow, "<Unknown Modifier>", ICON_NULL); /* right-align ------------------------------------------- */ subrow= uiLayoutRow(row, 0); @@ -633,7 +635,7 @@ void ANIM_uiTemplate_fmodifier_draw (uiLayout *layout, ID *id, ListBase *modifie /* 'mute' button */ - uiItemR(subrow, &ptr, "mute", UI_ITEM_R_ICON_ONLY, "", 0); + uiItemR(subrow, &ptr, "mute", UI_ITEM_R_ICON_ONLY, "", ICON_NULL); uiBlockSetEmboss(block, UI_EMBOSSN); diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c index 02e141a7a69..fb09b8d5c85 100644 --- a/source/blender/editors/animation/keyframes_draw.c +++ b/source/blender/editors/animation/keyframes_draw.c @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -39,6 +39,7 @@ #include "BLI_blenlib.h" #include "BLI_math.h" #include "BLI_dlrbTree.h" +#include "BLI_utildefines.h" #include "DNA_anim_types.h" #include "DNA_armature_types.h" @@ -47,6 +48,7 @@ #include "DNA_scene_types.h" #include "DNA_key_types.h" #include "DNA_lamp_types.h" +#include "DNA_lattice_types.h" #include "DNA_mesh_types.h" #include "DNA_material_types.h" #include "DNA_meta_types.h" @@ -58,7 +60,7 @@ #include "BKE_key.h" #include "BKE_material.h" #include "BKE_global.h" // XXX remove me! -#include "BKE_utildefines.h" + #include "BIF_gl.h" @@ -135,6 +137,49 @@ static void nupdate_ak_bezt (void *node, void *data) ak->key_type= BEZT_KEYTYPE_KEYFRAME; } +/* ......... */ + +/* Comparator callback used for ActKeyColumns and GPencil frame */ +static short compare_ak_gpframe (void *node, void *data) +{ + ActKeyColumn *ak= (ActKeyColumn *)node; + bGPDframe *gpf= (bGPDframe *)data; + + if (gpf->framenum < ak->cfra) + return -1; + else if (gpf->framenum > ak->cfra) + return 1; + else + return 0; +} + +/* New node callback used for building ActKeyColumns from GPencil frames */ +static DLRBT_Node *nalloc_ak_gpframe (void *data) +{ + ActKeyColumn *ak= MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumnGPF"); + bGPDframe *gpf= (bGPDframe *)data; + + /* store settings based on state of BezTriple */ + ak->cfra= gpf->framenum; + ak->sel= (gpf->flag & GP_FRAME_SELECT) ? SELECT : 0; + + /* set 'modified', since this is used to identify long keyframes */ + ak->modified = 1; + + return (DLRBT_Node *)ak; +} + +/* Node updater callback used for building ActKeyColumns from GPencil frames */ +static void nupdate_ak_gpframe (void *node, void *data) +{ + ActKeyColumn *ak= (ActKeyColumn *)node; + bGPDframe *gpf= (bGPDframe *)data; + + /* set selection status and 'touched' status */ + if (gpf->flag & GP_FRAME_SELECT) ak->sel = SELECT; + ak->modified += 1; +} + /* --------------- */ /* Add the given BezTriple to the given 'list' of Keyframes */ @@ -146,6 +191,15 @@ static void add_bezt_to_keycolumns_list(DLRBT_Tree *keys, BezTriple *bezt) BLI_dlrbTree_add(keys, compare_ak_bezt, nalloc_ak_bezt, nupdate_ak_bezt, bezt); } +/* Add the given GPencil Frame to the given 'list' of Keyframes */ +static void add_gpframe_to_keycolumns_list(DLRBT_Tree *keys, bGPDframe *gpf) +{ + if ELEM(NULL, keys, gpf) + return; + else + BLI_dlrbTree_add(keys, compare_ak_gpframe, nalloc_ak_gpframe, nupdate_ak_gpframe, gpf); +} + /* ActBeztColumns (Helpers for Long Keyframes) ------------------------------ */ /* maximum size of default buffer for BezTriple columns */ @@ -392,7 +446,7 @@ static const float _unit_diamond_shape[4][2] = { }; /* draw a simple diamond shape with OpenGL */ -void draw_keyframe_shape (float x, float y, float xscale, float hsize, short sel, short key_type, short mode) +void draw_keyframe_shape (float x, float y, float xscale, float hsize, short sel, short key_type, short mode, float alpha) { static GLuint displist1=0; static GLuint displist2=0; @@ -441,23 +495,30 @@ void draw_keyframe_shape (float x, float y, float xscale, float hsize, short sel switch (key_type) { case BEZT_KEYTYPE_BREAKDOWN: /* bluish frames for now */ { - if (sel) glColor3f(0.33f, 0.75f, 0.93f); - else glColor3f(0.70f, 0.86f, 0.91f); + if (sel) glColor4f(0.33f, 0.75f, 0.93f, alpha); + else glColor4f(0.70f, 0.86f, 0.91f, alpha); } break; case BEZT_KEYTYPE_EXTREME: /* redish frames for now */ { - if (sel) glColor3f(95.0f, 0.5f, 0.5f); - else glColor3f(0.91f, 0.70f, 0.80f); + if (sel) glColor4f(0.95f, 0.5f, 0.5f, alpha); + else glColor4f(0.91f, 0.70f, 0.80f, alpha); + } + break; + + case BEZT_KEYTYPE_JITTER: /* greenish frames for now? */ + { + if (sel) glColor4f(0.38f, 0.75f, 0.26f, alpha); + else glColor4f(0.58f, 0.90f, 0.46f, alpha); } break; case BEZT_KEYTYPE_KEYFRAME: /* traditional yellowish frames for now */ default: { - if (sel) UI_ThemeColorShade(TH_STRIP_SELECT, 50); - else glColor3f(0.91f, 0.91f, 0.91f); + if (sel) UI_ThemeColorShadeAlpha(TH_STRIP_SELECT, 50, -255*(1.0f-alpha)); + else glColor4f(0.91f, 0.91f, 0.91f, alpha); } break; } @@ -467,7 +528,7 @@ void draw_keyframe_shape (float x, float y, float xscale, float hsize, short sel if ELEM(mode, KEYFRAME_SHAPE_FRAME, KEYFRAME_SHAPE_BOTH) { /* exterior - black frame */ - glColor3ub(0, 0, 0); + glColor4f(0.0f, 0.0f, 0.0f, alpha); glCallList(displist1); } @@ -479,7 +540,7 @@ void draw_keyframe_shape (float x, float y, float xscale, float hsize, short sel glTranslatef(-x, -y, 0.0f); } -static void draw_keylist(View2D *v2d, DLRBT_Tree *keys, DLRBT_Tree *blocks, float ypos) +static void draw_keylist(View2D *v2d, DLRBT_Tree *keys, DLRBT_Tree *blocks, float ypos, short channelLocked) { ActKeyColumn *ak; ActKeyBlock *ab; @@ -522,6 +583,10 @@ static void draw_keylist(View2D *v2d, DLRBT_Tree *keys, DLRBT_Tree *blocks, floa /* draw keys */ if (keys) { + /* locked channels are less strongly shown, as feedback for locked channels in DopeSheet */ + // TODO: allow this opacity factor to be themed? + float kalpha = (channelLocked)? 0.35f : 1.0f; + for (ak= keys->first; ak; ak= ak->next) { /* optimisation: if keyframe doesn't appear within 5 units (screenspace) in visible area, don't draw * - this might give some improvements, since we current have to flip between view/region matrices @@ -532,7 +597,7 @@ static void draw_keylist(View2D *v2d, DLRBT_Tree *keys, DLRBT_Tree *blocks, floa /* draw using OpenGL - uglier but faster */ // NOTE1: a previous version of this didn't work nice for some intel cards // NOTE2: if we wanted to go back to icons, these are icon = (ak->sel & SELECT) ? ICON_SPACE2 : ICON_SPACE3; - draw_keyframe_shape(ak->cfra, ypos, xscale, 5.0f, (ak->sel & SELECT), ak->key_type, KEYFRAME_SHAPE_BOTH); + draw_keyframe_shape(ak->cfra, ypos, xscale, 5.0f, (ak->sel & SELECT), ak->key_type, KEYFRAME_SHAPE_BOTH, kalpha); } } @@ -553,7 +618,7 @@ void draw_summary_channel(View2D *v2d, bAnimContext *ac, float ypos) BLI_dlrbTree_linkedlist_sync(&keys); BLI_dlrbTree_linkedlist_sync(&blocks); - draw_keylist(v2d, &keys, &blocks, ypos); + draw_keylist(v2d, &keys, &blocks, ypos, 0); BLI_dlrbTree_free(&keys); BLI_dlrbTree_free(&blocks); @@ -571,7 +636,7 @@ void draw_scene_channel(View2D *v2d, bDopeSheet *ads, Scene *sce, float ypos) BLI_dlrbTree_linkedlist_sync(&keys); BLI_dlrbTree_linkedlist_sync(&blocks); - draw_keylist(v2d, &keys, &blocks, ypos); + draw_keylist(v2d, &keys, &blocks, ypos, 0); BLI_dlrbTree_free(&keys); BLI_dlrbTree_free(&blocks); @@ -589,7 +654,7 @@ void draw_object_channel(View2D *v2d, bDopeSheet *ads, Object *ob, float ypos) BLI_dlrbTree_linkedlist_sync(&keys); BLI_dlrbTree_linkedlist_sync(&blocks); - draw_keylist(v2d, &keys, &blocks, ypos); + draw_keylist(v2d, &keys, &blocks, ypos, 0); BLI_dlrbTree_free(&keys); BLI_dlrbTree_free(&blocks); @@ -607,7 +672,7 @@ void draw_fcurve_channel(View2D *v2d, AnimData *adt, FCurve *fcu, float ypos) BLI_dlrbTree_linkedlist_sync(&keys); BLI_dlrbTree_linkedlist_sync(&blocks); - draw_keylist(v2d, &keys, &blocks, ypos); + draw_keylist(v2d, &keys, &blocks, ypos, (fcu->flag & FCURVE_PROTECTED)); BLI_dlrbTree_free(&keys); BLI_dlrbTree_free(&blocks); @@ -625,7 +690,7 @@ void draw_agroup_channel(View2D *v2d, AnimData *adt, bActionGroup *agrp, float y BLI_dlrbTree_linkedlist_sync(&keys); BLI_dlrbTree_linkedlist_sync(&blocks); - draw_keylist(v2d, &keys, &blocks, ypos); + draw_keylist(v2d, &keys, &blocks, ypos, (agrp->flag & AGRP_PROTECTED)); BLI_dlrbTree_free(&keys); BLI_dlrbTree_free(&blocks); @@ -643,7 +708,7 @@ void draw_action_channel(View2D *v2d, AnimData *adt, bAction *act, float ypos) BLI_dlrbTree_linkedlist_sync(&keys); BLI_dlrbTree_linkedlist_sync(&blocks); - draw_keylist(v2d, &keys, &blocks, ypos); + draw_keylist(v2d, &keys, &blocks, ypos, 0); BLI_dlrbTree_free(&keys); BLI_dlrbTree_free(&blocks); @@ -655,11 +720,11 @@ void draw_gpl_channel(View2D *v2d, bDopeSheet *ads, bGPDlayer *gpl, float ypos) BLI_dlrbTree_init(&keys); - gpl_to_keylist(ads, gpl, &keys, NULL); + gpl_to_keylist(ads, gpl, &keys); BLI_dlrbTree_linkedlist_sync(&keys); - draw_keylist(v2d, &keys, NULL, ypos); + draw_keylist(v2d, &keys, NULL, ypos, (gpl->flag & GP_LAYER_LOCKED)); BLI_dlrbTree_free(&keys); } @@ -753,6 +818,8 @@ void ob_to_keylist(bDopeSheet *ads, Object *ob, DLRBT_Tree *keys, DLRBT_Tree *bl /* add material's data */ action_to_keylist(ma->adt, ma->adt->action, keys, blocks); + + // TODO: textures... } } @@ -808,6 +875,14 @@ void ob_to_keylist(bDopeSheet *ads, Object *ob, DLRBT_Tree *keys, DLRBT_Tree *bl action_to_keylist(me->adt, me->adt->action, keys, blocks); } break; + case OB_LATTICE: /* ------- Lattice ---------- */ + { + Lattice *lt= (Lattice *)ob->data; + + if ((lt->adt) && !(filterflag & ADS_FILTER_NOLAT)) + action_to_keylist(lt->adt, lt->adt->action, keys, blocks); + } + break; } /* Add Particle System Keyframes */ @@ -898,26 +973,14 @@ void action_to_keylist(AnimData *adt, bAction *act, DLRBT_Tree *keys, DLRBT_Tree } -void gpl_to_keylist(bDopeSheet *ads, bGPDlayer *gpl, DLRBT_Tree *keys, DLRBT_Tree *blocks) +void gpl_to_keylist(bDopeSheet *UNUSED(ads), bGPDlayer *gpl, DLRBT_Tree *keys) { bGPDframe *gpf; - ActKeyColumn *ak; if (gpl && keys) { - /* loop over frames, converting directly to 'keyframes' (should be in order too) */ - for (gpf= gpl->frames.first; gpf; gpf= gpf->next) { - ak= MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumn"); - BLI_addtail((ListBase *)keys, ak); - - ak->cfra= (float)gpf->framenum; - ak->modified = 1; - ak->key_type= 0; - - if (gpf->flag & GP_FRAME_SELECT) - ak->sel = SELECT; - else - ak->sel = 0; - } + /* although the frames should already be in an ordered list, they are not suitable for displaying yet */ + for (gpf= gpl->frames.first; gpf; gpf= gpf->next) + add_gpframe_to_keycolumns_list(keys, gpf); } } diff --git a/source/blender/editors/animation/keyframes_edit.c b/source/blender/editors/animation/keyframes_edit.c index 17d674784f8..23c2a5a013b 100644 --- a/source/blender/editors/animation/keyframes_edit.c +++ b/source/blender/editors/animation/keyframes_edit.c @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -33,12 +33,14 @@ #include "BLI_blenlib.h" #include "BLI_math.h" +#include "BLI_utildefines.h" #include "DNA_anim_types.h" #include "DNA_armature_types.h" #include "DNA_camera_types.h" #include "DNA_key_types.h" #include "DNA_lamp_types.h" +#include "DNA_lattice_types.h" #include "DNA_mesh_types.h" #include "DNA_material_types.h" #include "DNA_object_types.h" @@ -51,7 +53,7 @@ #include "BKE_fcurve.h" #include "BKE_key.h" #include "BKE_material.h" -#include "BKE_utildefines.h" + #include "ED_anim_api.h" #include "ED_keyframes_edit.h" @@ -318,6 +320,16 @@ static short ob_keyframes_loop(KeyframeEditData *ked, Object *ob, KeyframeEditFu } } break; + case OB_LATTICE: /* ---- Lattice ------ */ + { + Lattice *lt= (Lattice *)ob->data; + + if ((lt->adt) && !(filterflag & ADS_FILTER_NOLAT)) { + if (adt_keyframes_loop(ked, lt->adt, key_ok, key_cb, fcu_cb, filterflag)) + return 1; + } + } + break; } /* Add Particle System Keyframes */ @@ -369,7 +381,7 @@ static short scene_keyframes_loop(KeyframeEditData *ked, Scene *sce, KeyframeEdi } /* This function is used to loop over the keyframe data in a DopeSheet summary */ -static short summary_keyframes_loop(KeyframeEditData *ked, bAnimContext *ac, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb, int filterflag) +static short summary_keyframes_loop(KeyframeEditData *ked, bAnimContext *ac, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb, int UNUSED(filterflag)) { ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; @@ -541,7 +553,7 @@ static short ok_bezier_framerange(KeyframeEditData *ked, BezTriple *bezt) return ok; } -static short ok_bezier_selected(KeyframeEditData *ked, BezTriple *bezt) +static short ok_bezier_selected(KeyframeEditData *UNUSED(ked), BezTriple *bezt) { /* this macro checks all beztriple handles for selection... * only one of the verts has to be selected for this to be ok... @@ -677,7 +689,7 @@ void bezt_remap_times(KeyframeEditData *ked, BezTriple *bezt) /* Transform */ /* snaps the keyframe to the nearest frame */ -static short snap_bezier_nearest(KeyframeEditData *ked, BezTriple *bezt) +static short snap_bezier_nearest(KeyframeEditData *UNUSED(ked), BezTriple *bezt) { if (bezt->f2 & SELECT) bezt->vec[1][0]= (float)(floor(bezt->vec[1][0]+0.5)); @@ -713,7 +725,7 @@ static short snap_bezier_nearmarker(KeyframeEditData *ked, BezTriple *bezt) } /* make the handles have the same value as the key */ -static short snap_bezier_horizontal(KeyframeEditData *ked, BezTriple *bezt) +static short snap_bezier_horizontal(KeyframeEditData *UNUSED(ked), BezTriple *bezt) { if (bezt->f2 & SELECT) { bezt->vec[0][1]= bezt->vec[2][1]= bezt->vec[1][1]; @@ -768,7 +780,7 @@ static short mirror_bezier_cframe(KeyframeEditData *ked, BezTriple *bezt) return 0; } -static short mirror_bezier_yaxis(KeyframeEditData *ked, BezTriple *bezt) +static short mirror_bezier_yaxis(KeyframeEditData *UNUSED(ked), BezTriple *bezt) { float diff; @@ -780,7 +792,7 @@ static short mirror_bezier_yaxis(KeyframeEditData *ked, BezTriple *bezt) return 0; } -static short mirror_bezier_xaxis(KeyframeEditData *ked, BezTriple *bezt) +static short mirror_bezier_xaxis(KeyframeEditData *UNUSED(ked), BezTriple *bezt) { float diff; @@ -841,7 +853,7 @@ KeyframeEditFunc ANIM_editkeyframes_mirror(short type) /* Settings */ /* Sets the selected bezier handles to type 'auto' */ -static short set_bezier_auto(KeyframeEditData *ked, BezTriple *bezt) +static short set_bezier_auto(KeyframeEditData *UNUSED(ked), BezTriple *bezt) { if((bezt->f1 & SELECT) || (bezt->f3 & SELECT)) { if (bezt->f1 & SELECT) bezt->h1= HD_AUTO; /* the secret code for auto */ @@ -859,7 +871,7 @@ static short set_bezier_auto(KeyframeEditData *ked, BezTriple *bezt) } /* Sets the selected bezier handles to type 'vector' */ -static short set_bezier_vector(KeyframeEditData *ked, BezTriple *bezt) +static short set_bezier_vector(KeyframeEditData *UNUSED(ked), BezTriple *bezt) { if ((bezt->f1 & SELECT) || (bezt->f3 & SELECT)) { if (bezt->f1 & SELECT) bezt->h1= HD_VECT; @@ -879,7 +891,7 @@ static short set_bezier_vector(KeyframeEditData *ked, BezTriple *bezt) /* Queries if the handle should be set to 'free' or 'align' */ // NOTE: this was used for the 'toggle free/align' option // currently this isn't used, but may be restored later -static short bezier_isfree(KeyframeEditData *ked, BezTriple *bezt) +static short bezier_isfree(KeyframeEditData *UNUSED(ked), BezTriple *bezt) { if ((bezt->f1 & SELECT) && (bezt->h1)) return 1; if ((bezt->f3 & SELECT) && (bezt->h2)) return 1; @@ -887,7 +899,7 @@ static short bezier_isfree(KeyframeEditData *ked, BezTriple *bezt) } /* Sets selected bezier handles to type 'align' */ -static short set_bezier_align(KeyframeEditData *ked, BezTriple *bezt) +static short set_bezier_align(KeyframeEditData *UNUSED(ked), BezTriple *bezt) { if (bezt->f1 & SELECT) bezt->h1= HD_ALIGN; if (bezt->f3 & SELECT) bezt->h2= HD_ALIGN; @@ -895,7 +907,7 @@ static short set_bezier_align(KeyframeEditData *ked, BezTriple *bezt) } /* Sets selected bezier handles to type 'free' */ -static short set_bezier_free(KeyframeEditData *ked, BezTriple *bezt) +static short set_bezier_free(KeyframeEditData *UNUSED(ked), BezTriple *bezt) { if (bezt->f1 & SELECT) bezt->h1= HD_FREE; if (bezt->f3 & SELECT) bezt->h2= HD_FREE; @@ -925,21 +937,21 @@ KeyframeEditFunc ANIM_editkeyframes_handles(short code) /* ------- */ -static short set_bezt_constant(KeyframeEditData *ked, BezTriple *bezt) +static short set_bezt_constant(KeyframeEditData *UNUSED(ked), BezTriple *bezt) { if (bezt->f2 & SELECT) bezt->ipo= BEZT_IPO_CONST; return 0; } -static short set_bezt_linear(KeyframeEditData *ked, BezTriple *bezt) +static short set_bezt_linear(KeyframeEditData *UNUSED(ked), BezTriple *bezt) { if (bezt->f2 & SELECT) bezt->ipo= BEZT_IPO_LIN; return 0; } -static short set_bezt_bezier(KeyframeEditData *ked, BezTriple *bezt) +static short set_bezt_bezier(KeyframeEditData *UNUSED(ked), BezTriple *bezt) { if (bezt->f2 & SELECT) bezt->ipo= BEZT_IPO_BEZ; @@ -962,27 +974,34 @@ KeyframeEditFunc ANIM_editkeyframes_ipo(short code) /* ------- */ -static short set_keytype_keyframe(KeyframeEditData *ked, BezTriple *bezt) +static short set_keytype_keyframe(KeyframeEditData *UNUSED(ked), BezTriple *bezt) { if (bezt->f2 & SELECT) BEZKEYTYPE(bezt)= BEZT_KEYTYPE_KEYFRAME; return 0; } -static short set_keytype_breakdown(KeyframeEditData *ked, BezTriple *bezt) +static short set_keytype_breakdown(KeyframeEditData *UNUSED(ked), BezTriple *bezt) { if (bezt->f2 & SELECT) BEZKEYTYPE(bezt)= BEZT_KEYTYPE_BREAKDOWN; return 0; } -static short set_keytype_extreme(KeyframeEditData *ked, BezTriple *bezt) +static short set_keytype_extreme(KeyframeEditData *UNUSED(ked), BezTriple *bezt) { if (bezt->f2 & SELECT) BEZKEYTYPE(bezt)= BEZT_KEYTYPE_EXTREME; return 0; } +static short set_keytype_jitter(KeyframeEditData *UNUSED(ked), BezTriple *bezt) +{ + if (bezt->f2 & SELECT) + BEZKEYTYPE(bezt)= BEZT_KEYTYPE_JITTER; + return 0; +} + /* Set the interpolation type of the selected BezTriples in each F-Curve to the specified one */ KeyframeEditFunc ANIM_editkeyframes_keytype(short code) { @@ -993,6 +1012,9 @@ KeyframeEditFunc ANIM_editkeyframes_keytype(short code) case BEZT_KEYTYPE_EXTREME: /* extreme keyframe */ return set_keytype_extreme; + case BEZT_KEYTYPE_JITTER: /* jitter keyframe */ + return set_keytype_jitter; + case BEZT_KEYTYPE_KEYFRAME: /* proper keyframe */ default: return set_keytype_keyframe; @@ -1038,7 +1060,7 @@ static short select_bezier_subtract(KeyframeEditData *ked, BezTriple *bezt) return 0; } -static short select_bezier_invert(KeyframeEditData *ked, BezTriple *bezt) +static short select_bezier_invert(KeyframeEditData *UNUSED(ked), BezTriple *bezt) { /* Invert the selection for the whole bezier triple */ bezt->f2 ^= SELECT; diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c index 5073cfe08b8..aea8c2407b4 100644 --- a/source/blender/editors/animation/keyframes_general.c +++ b/source/blender/editors/animation/keyframes_general.c @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -34,6 +34,7 @@ #include "BLI_blenlib.h" #include "BLI_math.h" +#include "BLI_utildefines.h" #include "DNA_anim_types.h" #include "DNA_object_types.h" @@ -42,6 +43,12 @@ #include "BKE_fcurve.h" #include "BKE_utildefines.h" +#include "BKE_report.h" +#include "BKE_library.h" +#include "BKE_global.h" + +#include "RNA_access.h" +#include "RNA_enum_types.h" #include "ED_anim_api.h" #include "ED_keyframing.h" @@ -82,6 +89,12 @@ void delete_fcurve_key(FCurve *fcu, int index, short do_recalc) /* Delete this keyframe */ memmove(&fcu->bezt[index], &fcu->bezt[index+1], sizeof(BezTriple)*(fcu->totvert-index-1)); fcu->totvert--; + + if (fcu->totvert == 0) { + if (fcu->bezt) + MEM_freeN(fcu->bezt); + fcu->bezt= NULL; + } /* recalc handles - only if it won't cause problems */ if (do_recalc) @@ -106,11 +119,18 @@ void delete_fcurve_keys(FCurve *fcu) } /* Free the array of BezTriples if there are not keyframes */ - if (fcu->totvert == 0) { - if (fcu->bezt) - MEM_freeN(fcu->bezt); - fcu->bezt= NULL; - } + if(fcu->totvert == 0) + clear_fcurve_keys(fcu); +} + + +void clear_fcurve_keys(FCurve *fcu) +{ + if (fcu->bezt) + MEM_freeN(fcu->bezt); + fcu->bezt= NULL; + + fcu->totvert= 0; } /* ---------------- */ @@ -366,7 +386,7 @@ void sample_fcurve (FCurve *fcu) int sfra, range; int i, n, nIndex; - if(fcu->bezt==NULL) /* ignore baked */ + if (fcu->bezt==NULL) /* ignore baked */ return; /* find selected keyframes... once pair has been found, add keyframes */ @@ -433,8 +453,10 @@ void sample_fcurve (FCurve *fcu) */ /* globals for copy/paste data (like for other copy/paste buffers) */ -ListBase animcopybuf = {NULL, NULL}; +static ListBase animcopybuf = {NULL, NULL}; static float animcopy_firstframe= 999999999.0f; +static float animcopy_lastframe= -999999999.0f; +static float animcopy_cfra= 0.0; /* datatype for use in copy/paste buffer */ typedef struct tAnimCopybufItem { @@ -447,6 +469,8 @@ typedef struct tAnimCopybufItem { int totvert; /* number of keyframes stored for this channel */ BezTriple *bezt; /* keyframes in buffer */ + + short id_type; /* Result of GS(id->name)*/ } tAnimCopybufItem; @@ -475,6 +499,7 @@ void free_anim_copybuf (void) /* restore initial state */ animcopybuf.first= animcopybuf.last= NULL; animcopy_firstframe= 999999999.0f; + animcopy_lastframe= -999999999.0f; } /* ------------------- */ @@ -483,6 +508,7 @@ void free_anim_copybuf (void) short copy_animedit_keys (bAnimContext *ac, ListBase *anim_data) { bAnimListElem *ale; + Scene *scene= ac->scene; /* clear buffer first */ free_anim_copybuf(); @@ -491,7 +517,7 @@ short copy_animedit_keys (bAnimContext *ac, ListBase *anim_data) for (ale= anim_data->first; ale; ale= ale->next) { FCurve *fcu= (FCurve *)ale->key_data; tAnimCopybufItem *aci; - BezTriple *bezt, *newbuf; + BezTriple *bezt, *nbezt, *newbuf; int i; /* firstly, check if F-Curve has any selected keyframes @@ -504,6 +530,7 @@ short copy_animedit_keys (bAnimContext *ac, ListBase *anim_data) /* init copybuf item info */ aci= MEM_callocN(sizeof(tAnimCopybufItem), "AnimCopybufItem"); aci->id= ale->id; + aci->id_type= GS(ale->id->name); aci->grp= fcu->grp; aci->rna_path= MEM_dupallocN(fcu->rna_path); aci->array_index= fcu->array_index; @@ -521,7 +548,11 @@ short copy_animedit_keys (bAnimContext *ac, ListBase *anim_data) memcpy(newbuf, aci->bezt, sizeof(BezTriple)*(aci->totvert)); /* copy current beztriple across too */ - *(newbuf + aci->totvert)= *bezt; + nbezt= &newbuf[aci->totvert]; + *nbezt= *bezt; + + /* ensure copy buffer is selected so pasted keys are selected */ + BEZ_SEL(nbezt); /* free old array and set the new */ if (aci->bezt) MEM_freeN(aci->bezt); @@ -531,6 +562,8 @@ short copy_animedit_keys (bAnimContext *ac, ListBase *anim_data) /* check if this is the earliest frame encountered so far */ if (bezt->vec[1][0] < animcopy_firstframe) animcopy_firstframe= bezt->vec[1][0]; + if (bezt->vec[1][0] > animcopy_lastframe) + animcopy_lastframe= bezt->vec[1][0]; } } @@ -539,76 +572,287 @@ short copy_animedit_keys (bAnimContext *ac, ListBase *anim_data) /* check if anything ended up in the buffer */ if (ELEM(NULL, animcopybuf.first, animcopybuf.last)) return -1; - + + /* incase 'relative' paste method is used */ + animcopy_cfra= CFRA; + /* everything went fine */ return 0; } +/* ------------------- */ + +/* most strict method: exact matches only */ +static tAnimCopybufItem *pastebuf_match_path_full(FCurve *fcu, const short from_single, const short to_simple) +{ + tAnimCopybufItem *aci; + + for (aci= animcopybuf.first; aci; aci= aci->next) { + /* check that paths exist */ + if (to_simple || (aci->rna_path && fcu->rna_path)) { + if (to_simple || (strcmp(aci->rna_path, fcu->rna_path) == 0)) { + if ((from_single) || (aci->array_index == fcu->array_index)) + break; + } + } + } + + return aci; +} + +/* medium match strictness: path match only (i.e. ignore ID) */ +static tAnimCopybufItem *pastebuf_match_path_property(FCurve *fcu, const short from_single, const short UNUSED(to_simple)) +{ + tAnimCopybufItem *aci; + + for (aci= animcopybuf.first; aci; aci= aci->next) { + /* check that paths exist */ + if (aci->rna_path && fcu->rna_path) { + /* find the property of the fcurve and compare against the end of the tAnimCopybufItem + * more involved since it needs to to path lookups. + * This is not 100% reliable since the user could be editing the curves on a path that wont + * resolve, or a bone could be renamed after copying for eg. but in normal copy & paste + * this should work out ok. + */ + if (BLI_findindex(which_libbase(G.main, aci->id_type), aci->id) == -1) { + /* pedantic but the ID could have been removed, and beats crashing! */ + printf("paste_animedit_keys: error ID has been removed!\n"); + } + else { + PointerRNA id_ptr, rptr; + PropertyRNA *prop; + + RNA_id_pointer_create(aci->id, &id_ptr); + RNA_path_resolve(&id_ptr, aci->rna_path, &rptr, &prop); + + if (prop) { + const char *identifier= RNA_property_identifier(prop); + int len_id = strlen(identifier); + int len_path = strlen(fcu->rna_path); + if (len_id <= len_path) { + /* note, paths which end with "] will fail with this test - Animated ID Props */ + if (strcmp(identifier, fcu->rna_path + (len_path-len_id))==0) { + if ((from_single) || (aci->array_index == fcu->array_index)) + break; + } + } + } + else { + printf("paste_animedit_keys: failed to resolve path id:%s, '%s'!\n", aci->id->name, aci->rna_path); + } + } + } + } + + return aci; +} + +/* least strict matching heuristic: indices only */ +static tAnimCopybufItem *pastebuf_match_index_only(FCurve *fcu, const short from_single, const short UNUSED(to_simple)) +{ + tAnimCopybufItem *aci; + + for (aci= animcopybuf.first; aci; aci= aci->next) { + /* check that paths exist */ + if ((from_single) || (aci->array_index == fcu->array_index)) { + break; + } + } + + return aci; +} + +/* ................ */ + +/* helper for paste_animedit_keys() - performs the actual pasting */ +static void paste_animedit_keys_fcurve(FCurve *fcu, tAnimCopybufItem *aci, float offset, const eKeyMergeMode merge_mode) +{ + BezTriple *bezt; + int i; + + /* First de-select existing FCuvre */ + for (i=0, bezt=fcu->bezt; i < fcu->totvert; i++, bezt++) { + bezt->f2 &= ~SELECT; + } + + /* mix mode with existing data */ + switch (merge_mode) { + case KEYFRAME_PASTE_MERGE_MIX: + /* do-nothing */ + break; + + case KEYFRAME_PASTE_MERGE_OVER: + /* remove all keys */ + clear_fcurve_keys(fcu); + break; + + case KEYFRAME_PASTE_MERGE_OVER_RANGE: + case KEYFRAME_PASTE_MERGE_OVER_RANGE_ALL: + { + float f_min; + float f_max; + + if (merge_mode==KEYFRAME_PASTE_MERGE_OVER_RANGE) { + f_min= aci->bezt[0].vec[1][0] + offset; + f_max= aci->bezt[aci->totvert-1].vec[1][0] + offset; + } + else { /* Entire Range */ + f_min= animcopy_firstframe + offset; + f_max= animcopy_lastframe + offset; + } + + /* remove keys in range */ + if (f_min < f_max) { + /* select verts in range for removal */ + for (i=0, bezt=fcu->bezt; i < fcu->totvert; i++, bezt++) { + if ((f_min < bezt[0].vec[1][0]) && (bezt[0].vec[1][0] < f_max)) { + bezt->f2 |= SELECT; + } + } + + /* remove frames in the range */ + delete_fcurve_keys(fcu); + } + break; + } + } + + /* just start pasting, with the the first keyframe on the current frame, and so on */ + for (i=0, bezt=aci->bezt; i < aci->totvert; i++, bezt++) { + /* temporarily apply offset to src beztriple while copying */ + bezt->vec[0][0] += offset; + bezt->vec[1][0] += offset; + bezt->vec[2][0] += offset; + + /* insert the keyframe + * NOTE: no special flags here for now + */ + insert_bezt_fcurve(fcu, bezt, 0); + + /* un-apply offset from src beztriple after copying */ + bezt->vec[0][0] -= offset; + bezt->vec[1][0] -= offset; + bezt->vec[2][0] -= offset; + } + + /* recalculate F-Curve's handles? */ + calchandles_fcurve(fcu); +} + +/* ------------------- */ + +EnumPropertyItem keyframe_paste_offset_items[] = { + {KEYFRAME_PASTE_OFFSET_CFRA_START, "START", 0, "Frame Start", "Paste keys starting at current frame"}, + {KEYFRAME_PASTE_OFFSET_CFRA_END, "END", 0, "Frame End", "Paste keys ending at current frame"}, + {KEYFRAME_PASTE_OFFSET_CFRA_RELATIVE, "RELATIVE", 0, "Frame Relative", "Paste keys relative to the current frame when copying"}, + {KEYFRAME_PASTE_OFFSET_NONE, "NONE", 0, "No Offset", "Paste keys from original time"}, + {0, NULL, 0, NULL, NULL}}; + +EnumPropertyItem keyframe_paste_merge_items[] = { + {KEYFRAME_PASTE_MERGE_MIX, "MIX", 0, "Mix", "Overlay existing with new keys"}, + {KEYFRAME_PASTE_MERGE_OVER, "OVER_ALL", 0, "Overwrite All", "Replace all keys"}, + {KEYFRAME_PASTE_MERGE_OVER_RANGE, "OVER_RANGE", 0, "Overwrite Range", "Overwrite keys in pasted range"}, + {KEYFRAME_PASTE_MERGE_OVER_RANGE_ALL, "OVER_RANGE_ALL", 0, "Overwrite Entire Range", "Overwrite keys in pasted range, using the range of all copied keys."}, + {0, NULL, 0, NULL, NULL}}; + + /* This function pastes data from the keyframes copy/paste buffer */ -short paste_animedit_keys (bAnimContext *ac, ListBase *anim_data) +short paste_animedit_keys (bAnimContext *ac, ListBase *anim_data, + const eKeyPasteOffset offset_mode, const eKeyMergeMode merge_mode) { bAnimListElem *ale; + const Scene *scene= (ac->scene); - const float offset = (float)(CFRA - animcopy_firstframe); - short no_name= 0; + const short from_single= (animcopybuf.first == animcopybuf.last); + const short to_simple= (anim_data->first == anim_data->last); + + float offset = 0.0f; + int pass; + /* check if buffer is empty */ - if (ELEM(NULL, animcopybuf.first, animcopybuf.last)) { - //error("No data in buffer to paste"); + if (animcopybuf.first == NULL) { + BKE_report(ac->reports, RPT_WARNING, "No data in buffer to paste"); + return -1; + } + + if (anim_data->first == NULL) { + BKE_report(ac->reports, RPT_WARNING, "No FCurves to paste into"); return -1; } - /* check if single channel in buffer (disregard names if so) */ - if (animcopybuf.first == animcopybuf.last) - no_name= 1; - /* from selected channels */ - for (ale= anim_data->first; ale; ale= ale->next) { - FCurve *fcu = (FCurve *)ale->data; /* destination F-Curve */ - tAnimCopybufItem *aci= NULL; - BezTriple *bezt; - int i; + /* mathods of offset */ + switch(offset_mode) { + case KEYFRAME_PASTE_OFFSET_CFRA_START: + offset= (float)(CFRA - animcopy_firstframe); + break; + case KEYFRAME_PASTE_OFFSET_CFRA_END: + offset= (float)(CFRA - animcopy_lastframe); + break; + case KEYFRAME_PASTE_OFFSET_CFRA_RELATIVE: + offset= (float)(CFRA - animcopy_cfra); + break; + case KEYFRAME_PASTE_OFFSET_NONE: + offset= 0.0f; + break; + } + + if (from_single && to_simple) { + /* 1:1 match, no tricky checking, just paste */ + FCurve *fcu; + tAnimCopybufItem *aci; + + ale= anim_data->first; + fcu= (FCurve *)ale->data; /* destination F-Curve */ + aci= animcopybuf.first; - /* find buffer item to paste from - * - if names don't matter (i.e. only 1 channel in buffer), don't check id/group - * - if names do matter, only check if id-type is ok for now (group check is not that important) - * - most importantly, rna-paths should match (array indices are unimportant for now) + paste_animedit_keys_fcurve(fcu, aci, offset, merge_mode); + } + else { + /* from selected channels + * This "passes" system aims to try to find "matching" channels to paste keyframes + * into with increasingly loose matching heuristics. The process finishes when at least + * one F-Curve has been pasted into. */ - // TODO: the matching algorithm here is pathetic! - for (aci= animcopybuf.first; aci; aci= aci->next) { - /* check that paths exist */ - if (aci->rna_path && fcu->rna_path) { - // FIXME: this breaks for bone names! - if (strcmp(aci->rna_path, fcu->rna_path) == 0) { - /* should be a match unless there's more than one of these */ - if ((no_name) || (aci->array_index == fcu->array_index)) + for (pass= 0; pass < 3; pass++) { + unsigned int totmatch= 0; + + for (ale= anim_data->first; ale; ale= ale->next) { + /* find buffer item to paste from + * - if names don't matter (i.e. only 1 channel in buffer), don't check id/group + * - if names do matter, only check if id-type is ok for now (group check is not that important) + * - most importantly, rna-paths should match (array indices are unimportant for now) + */ + FCurve *fcu = (FCurve *)ale->data; /* destination F-Curve */ + tAnimCopybufItem *aci= NULL; + + switch (pass) { + case 0: + /* most strict, must be exact path match data_path & index */ + aci= pastebuf_match_path_full(fcu, from_single, to_simple); + break; + + case 1: + /* less strict, just compare property names */ + aci= pastebuf_match_path_property(fcu, from_single, to_simple); + break; + + case 2: + /* Comparing properties gave no results, so just do index comparisons */ + aci= pastebuf_match_index_only(fcu, from_single, to_simple); break; } - } - } - - - /* copy the relevant data from the matching buffer curve */ - if (aci) { - /* just start pasting, with the the first keyframe on the current frame, and so on */ - for (i=0, bezt=aci->bezt; i < aci->totvert; i++, bezt++) { - /* temporarily apply offset to src beztriple while copying */ - bezt->vec[0][0] += offset; - bezt->vec[1][0] += offset; - bezt->vec[2][0] += offset; - /* insert the keyframe - * NOTE: no special flags here for now - */ - insert_bezt_fcurve(fcu, bezt, 0); - - /* un-apply offset from src beztriple after copying */ - bezt->vec[0][0] -= offset; - bezt->vec[1][0] -= offset; - bezt->vec[2][0] -= offset; + /* copy the relevant data from the matching buffer curve */ + if (aci) { + totmatch++; + paste_animedit_keys_fcurve(fcu, aci, offset, merge_mode); + } } - /* recalculate F-Curve's handles? */ - calchandles_fcurve(fcu); + /* dont continue if some fcurves were pasted */ + if (totmatch) + break; } } diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index fc5649be869..adc580c253d 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -38,6 +38,7 @@ #include "BLI_blenlib.h" #include "BLI_math.h" #include "BLI_dynstr.h" +#include "BLI_utildefines.h" #include "DNA_anim_types.h" #include "DNA_armature_types.h" @@ -49,6 +50,7 @@ #include "BKE_animsys.h" #include "BKE_action.h" +#include "BKE_armature.h" #include "BKE_constraint.h" #include "BKE_depsgraph.h" #include "BKE_fcurve.h" @@ -72,6 +74,7 @@ #include "RNA_access.h" #include "RNA_define.h" +#include "RNA_enum_types.h" #include "anim_intern.h" @@ -86,15 +89,15 @@ short ANIM_get_keyframing_flags (Scene *scene, short incl_mode) /* standard flags */ { /* visual keying */ - if (IS_AUTOKEY_FLAG(AUTOMATKEY)) + if (IS_AUTOKEY_FLAG(scene, AUTOMATKEY)) flag |= INSERTKEY_MATRIX; /* only needed */ - if (IS_AUTOKEY_FLAG(INSERTNEEDED)) + if (IS_AUTOKEY_FLAG(scene, INSERTNEEDED)) flag |= INSERTKEY_NEEDED; - /* default F-Curve color mode - RGB from XYZ indicies */ - if (IS_AUTOKEY_FLAG(XYZ2RGB)) + /* default F-Curve color mode - RGB from XYZ indices */ + if (IS_AUTOKEY_FLAG(scene, XYZ2RGB)) flag |= INSERTKEY_XYZ2RGB; } @@ -230,6 +233,10 @@ int insert_bezt_fcurve (FCurve *fcu, BezTriple *bezt, short flag) dst->vec[1][1] += dy; dst->vec[2][1] += dy; + dst->f1= bezt->f1; + dst->f2= bezt->f2; + dst->f3= bezt->f3; + // TODO: perform some other operations? } } @@ -287,13 +294,12 @@ int insert_bezt_fcurve (FCurve *fcu, BezTriple *bezt, short flag) */ int insert_vert_fcurve (FCurve *fcu, float x, float y, short flag) { - BezTriple beztr; + BezTriple beztr= {{{0}}}; int a; /* set all three points, for nicer start position * NOTE: +/- 1 on vec.x for left and right handles is so that 'free' handles work ok... */ - memset(&beztr, 0, sizeof(BezTriple)); beztr.vec[0][0]= x-1.0f; beztr.vec[0][1]= y; beztr.vec[1][0]= x; @@ -348,7 +354,7 @@ enum { KEYNEEDED_JUSTADD, KEYNEEDED_DELPREV, KEYNEEDED_DELNEXT -} eKeyNeededStatus; +} /*eKeyNeededStatus*/; /* This helper function determines whether a new keyframe is needed */ /* Cases where keyframes should not be added: @@ -569,6 +575,7 @@ static short visualkey_can_use (PointerRNA *ptr, PropertyRNA *prop) case CONSTRAINT_TYPE_CHILDOF: return 1; case CONSTRAINT_TYPE_TRANSFORM: + case CONSTRAINT_TYPE_TRANSLIKE: return 1; case CONSTRAINT_TYPE_FOLLOWPATH: return 1; @@ -636,51 +643,48 @@ static float visualkey_get_value (PointerRNA *ptr, PropertyRNA *prop, int array_ if (strstr(identifier, "location")) { return ob->obmat[3][array_index]; } - else if (strstr(identifier, "rotation")) { + else if (strstr(identifier, "rotation_euler")) { float eul[3]; - mat4_to_eul( eul,ob->obmat); + mat4_to_eulO(eul, ob->rotmode, ob->obmat); return eul[array_index]; } + // FIXME: other types of rotation don't work } } else if (ptr->type == &RNA_PoseBone) { - Object *ob= (Object *)ptr->id.data; /* we assume that this is always set, and is an object */ bPoseChannel *pchan= (bPoseChannel *)ptr->data; - float tmat[4][4]; + bPoseChannel tchan; - /* Although it is not strictly required for this particular space conversion, - * arg1 must not be null, as there is a null check for the other conversions to - * be safe. Therefore, the active object is passed here, and in many cases, this - * will be what owns the pose-channel that is getting this anyway. + /* make a copy of pchan so that we can apply and decompose its chan_mat, thus getting the + * rest-pose to pose-mode transform that got stored there at the end of posing calculations + * for B-Bone deforms to use + * - it should be safe to just make a local copy like this, since we're not doing anything with the copied pointers */ - copy_m4_m4(tmat, pchan->pose_mat); - constraint_mat_convertspace(ob, pchan, tmat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL); + memcpy(&tchan, pchan, sizeof(bPoseChannel)); + pchan_apply_mat4(&tchan, pchan->chan_mat, TRUE); /* Loc, Rot/Quat keyframes are supported... */ if (strstr(identifier, "location")) { /* only use for non-connected bones */ if ((pchan->bone->parent) && !(pchan->bone->flag & BONE_CONNECTED)) - return tmat[3][array_index]; + return tchan.loc[array_index]; else if (pchan->bone->parent == NULL) - return tmat[3][array_index]; + return tchan.loc[array_index]; } else if (strstr(identifier, "rotation_euler")) { - float eul[3]; - - /* euler-rotation test before standard rotation, as standard rotation does quats */ - mat4_to_eulO( eul, pchan->rotmode,tmat); - return eul[array_index]; + return tchan.eul[array_index]; } else if (strstr(identifier, "rotation_quaternion")) { - float trimat[3][3], quat[4]; - - copy_m3_m4(trimat, tmat); - mat3_to_quat_is_ok( quat,trimat); - - return quat[array_index]; + return tchan.quat[array_index]; + } + else if (strstr(identifier, "rotation_axisangle")) { + /* w = 0, x,y,z = 1,2,3 */ + if (array_index == 0) + return tchan.rotAngle; + else + return tchan.rotAxis[array_index - 1]; } - // TODO: axis-angle... } /* as the function hasn't returned yet, read value from system in the default way */ @@ -697,25 +701,26 @@ static float visualkey_get_value (PointerRNA *ptr, PropertyRNA *prop, int array_ * 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) +short insert_keyframe_direct (ReportList *reports, 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"); + BKE_report(reports, RPT_ERROR, "No F-Curve to add keyframes to"); return 0; } /* F-Curve not editable? */ - if ( (fcu->flag & FCURVE_PROTECTED) || ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) ) { - if (G.f & G_DEBUG) - printf("WARNING: not inserting keyframe for locked F-Curve \n"); + if (fcurve_is_keyframable(fcu) == 0) { + BKE_reportf(reports, RPT_ERROR, + "F-Curve with path = '%s' [%d] cannot be keyframed. Ensure that it is not locked or sampled. Also, try removing F-Modifiers.", + fcu->rna_path, fcu->array_index); 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"); + BKE_report(reports, RPT_ERROR, "No RNA-pointer available to retrieve values for keyframing from"); return 0; } if (prop == NULL) { @@ -724,9 +729,11 @@ short insert_keyframe_direct (PointerRNA ptr, PropertyRNA *prop, FCurve *fcu, fl /* 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>"; + const 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); + BKE_reportf(reports, RPT_ERROR, + "Could not insert keyframe, as RNA Path is invalid for the given ID (ID = %s, Path = %s)", + idname, fcu->rna_path); return 0; } else { @@ -815,7 +822,7 @@ short insert_keyframe_direct (PointerRNA ptr, PropertyRNA *prop, FCurve *fcu, fl * * index of -1 keys all array indices */ -short insert_keyframe (ID *id, bAction *act, const char group[], const char rna_path[], int array_index, float cfra, short flag) +short insert_keyframe (ReportList *reports, ID *id, bAction *act, const char group[], const char rna_path[], int array_index, float cfra, short flag) { PointerRNA id_ptr, ptr; PropertyRNA *prop = NULL; @@ -825,13 +832,14 @@ short insert_keyframe (ID *id, bAction *act, const char group[], const char rna_ /* validate pointer first - exit if failure */ if (id == NULL) { - printf("Insert Key: no ID-block to insert keyframe in (Path = %s) \n", rna_path); + BKE_reportf(reports, RPT_ERROR, "No ID-block to insert keyframe in (Path = %s)", rna_path); return 0; } RNA_id_pointer_create(id, &id_ptr); if ((RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop) == 0) || (prop == NULL)) { - printf("Insert Key: Could not insert keyframe, as RNA Path is invalid for the given ID (ID = %s, Path = %s)\n", + BKE_reportf(reports, RPT_ERROR, + "Could not insert keyframe, as RNA Path is invalid for the given ID (ID = %s, Path = %s)", (id)? id->name : "<Missing ID-Block>", rna_path); return 0; } @@ -844,7 +852,9 @@ short insert_keyframe (ID *id, bAction *act, const char group[], const char rna_ act= verify_adt_action(id, 1); if (act == NULL) { - printf("Insert Key: Could not insert keyframe, as this type does not support animation data (ID = %s, Path = %s)\n", id->name, rna_path); + BKE_reportf(reports, RPT_ERROR, + "Could not insert keyframe, as this type does not support animation data (ID = %s, Path = %s)", + id->name, rna_path); return 0; } @@ -900,7 +910,7 @@ short insert_keyframe (ID *id, bAction *act, const char group[], const char rna_ } /* insert keyframe */ - ret += insert_keyframe_direct(ptr, prop, fcu, cfra, flag); + ret += insert_keyframe_direct(reports, ptr, prop, fcu, cfra, flag); } } @@ -917,7 +927,7 @@ short insert_keyframe (ID *id, bAction *act, const char group[], const char rna_ * The flag argument is used for special settings that alter the behaviour of * the keyframe deletion. These include the quick refresh options. */ -short delete_keyframe (ID *id, bAction *act, const char group[], const char rna_path[], int array_index, float cfra, short flag) +short delete_keyframe (ReportList *reports, ID *id, bAction *act, const char group[], const char rna_path[], int array_index, float cfra, short UNUSED(flag)) { AnimData *adt= BKE_animdata_from_id(id); PointerRNA id_ptr, ptr; @@ -927,14 +937,14 @@ short delete_keyframe (ID *id, bAction *act, const char group[], const char rna_ /* sanity checks */ if ELEM(NULL, id, adt) { - printf("ERROR: no ID-block and/or AnimData to delete keyframe from \n"); + BKE_report(reports, RPT_ERROR, "No ID-Block and/Or AnimData to delete keyframe from"); return 0; } /* validate pointer first - exit if failure */ RNA_id_pointer_create(id, &id_ptr); if ((RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop) == 0) || (prop == NULL)) { - printf("Delete Key: Could not delete keyframe, as RNA Path is invalid for the given ID (ID = %s, Path = %s)\n", id->name, rna_path); + BKE_reportf(reports, RPT_ERROR, "Could not delete keyframe, as RNA Path is invalid for the given ID (ID = %s, Path = %s)", id->name, rna_path); return 0; } @@ -953,7 +963,7 @@ short delete_keyframe (ID *id, bAction *act, const char group[], const char rna_ cfra= BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP); } else { - printf("ERROR: no Action to delete keyframes from for ID = %s \n", id->name); + BKE_reportf(reports, RPT_ERROR, "No Action to delete keyframes from for ID = %s \n", id->name); return 0; } } @@ -997,7 +1007,7 @@ short delete_keyframe (ID *id, bAction *act, const char group[], const char rna_ if ( (fcu->flag & FCURVE_PROTECTED) || ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) ) { if (G.f & G_DEBUG) - printf("WARNING: not inserting keyframe for locked F-Curve \n"); + printf("WARNING: not deleting keyframe for locked F-Curve \n"); continue; } @@ -1027,7 +1037,7 @@ short delete_keyframe (ID *id, bAction *act, const char group[], const char rna_ enum { COMMONKEY_MODE_INSERT = 0, COMMONKEY_MODE_DELETE, -} eCommonModifyKey_Modes; +} /*eCommonModifyKey_Modes*/; /* Polling callback for use with ANIM_*_keyframe() operators * This is based on the standard ED_operator_areaactive callback, @@ -1064,7 +1074,7 @@ static int insert_key_exec (bContext *C, wmOperator *op) Main *bmain= CTX_data_main(C); Scene *scene= CTX_data_scene(C); KeyingSet *ks= NULL; - int type= RNA_int_get(op->ptr, "type"); + int type= RNA_enum_get(op->ptr, "type"); float cfra= (float)CFRA; // XXX for now, don't bother about all the yucky offset crap short success; @@ -1129,11 +1139,12 @@ void ANIM_OT_keyframe_insert (wmOperatorType *ot) /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - /* keyingset to use - * - here the type is int not enum, since many of the indicies here are determined dynamically - */ - prop= RNA_def_int(ot->srna, "type", 0, INT_MIN, INT_MAX, "Keying Set Number", "Index (determined internally) of the Keying Set to use", 0, 1); + /* keyingset to use (dynamic enum) */ + prop= RNA_def_enum(ot->srna, "type", DummyRNA_DEFAULT_items, 0, "Keying Set", "The Keying Set to use"); + RNA_def_enum_funcs(prop, ANIM_keying_sets_enum_itemf); RNA_def_property_flag(prop, PROP_HIDDEN); + ot->prop= prop; + /* confirm whether a keyframe was added by showing a popup * - by default, this is enabled, since this operator is assumed to be called independently */ @@ -1146,7 +1157,7 @@ void ANIM_OT_keyframe_insert (wmOperatorType *ot) * then calls the menu if necessary before */ -static int insert_key_menu_invoke (bContext *C, wmOperator *op, wmEvent *event) +static int insert_key_menu_invoke (bContext *C, wmOperator *op, wmEvent *UNUSED(event)) { Scene *scene= CTX_data_scene(C); @@ -1158,7 +1169,7 @@ static int insert_key_menu_invoke (bContext *C, wmOperator *op, wmEvent *event) } else { /* just call the exec() on the active keyingset */ - RNA_int_set(op->ptr, "type", 0); + RNA_enum_set(op->ptr, "type", 0); RNA_boolean_set(op->ptr, "confirm_success", 1); return op->type->exec(C, op); @@ -1172,6 +1183,7 @@ void ANIM_OT_keyframe_insert_menu (wmOperatorType *ot) /* identifiers */ ot->name= "Insert Keyframe Menu"; ot->idname= "ANIM_OT_keyframe_insert_menu"; + ot->description= "Insert Keyframes for specified Keying Set, with menu of available Keying Sets if undefined"; /* callbacks */ ot->invoke= insert_key_menu_invoke; @@ -1181,17 +1193,19 @@ void ANIM_OT_keyframe_insert_menu (wmOperatorType *ot) /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - /* keyingset to use - * - here the type is int not enum, since many of the indicies here are determined dynamically - */ - prop= RNA_def_int(ot->srna, "type", 0, INT_MIN, INT_MAX, "Keying Set Number", "Index (determined internally) of the Keying Set to use", 0, 1); + /* keyingset to use (dynamic enum) */ + prop= RNA_def_enum(ot->srna, "type", DummyRNA_DEFAULT_items, 0, "Keying Set", "The Keying Set to use"); + RNA_def_enum_funcs(prop, ANIM_keying_sets_enum_itemf); RNA_def_property_flag(prop, PROP_HIDDEN); + ot->prop= prop; + /* confirm whether a keyframe was added by showing a popup * - by default, this is disabled so that if a menu is shown, this doesn't come up too */ // XXX should this just be always on? prop= RNA_def_boolean(ot->srna, "confirm_success", 0, "Confirm Successful Insert", "Show a popup when the keyframes get successfully added"); RNA_def_property_flag(prop, PROP_HIDDEN); + /* whether the menu should always be shown * - by default, the menu should only be shown when there is no active Keying Set (2.5 behaviour), * although in some cases it might be useful to always shown (pre 2.5 behaviour) @@ -1207,7 +1221,7 @@ static int delete_key_exec (bContext *C, wmOperator *op) Main *bmain= CTX_data_main(C); Scene *scene= CTX_data_scene(C); KeyingSet *ks= NULL; - int type= RNA_int_get(op->ptr, "type"); + int type= RNA_enum_get(op->ptr, "type"); float cfra= (float)CFRA; // XXX for now, don't bother about all the yucky offset crap short success; @@ -1258,6 +1272,8 @@ static int delete_key_exec (bContext *C, wmOperator *op) void ANIM_OT_keyframe_delete (wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name= "Delete Keyframe"; ot->idname= "ANIM_OT_keyframe_delete"; @@ -1270,10 +1286,12 @@ void ANIM_OT_keyframe_delete (wmOperatorType *ot) /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - /* keyingset to use - * - here the type is int not enum, since many of the indicies here are determined dynamically - */ - RNA_def_int(ot->srna, "type", 0, INT_MIN, INT_MAX, "Keying Set Number", "Index (determined internally) of the Keying Set to use", 0, 1); + /* keyingset to use (dynamic enum) */ + prop= RNA_def_enum(ot->srna, "type", DummyRNA_DEFAULT_items, 0, "Keying Set", "The Keying Set to use"); + RNA_def_enum_funcs(prop, ANIM_keying_sets_enum_itemf); + RNA_def_property_flag(prop, PROP_HIDDEN); + ot->prop= prop; + /* confirm whether a keyframe was added by showing a popup * - by default, this is enabled, since this operator is assumed to be called independently */ @@ -1308,7 +1326,7 @@ static int delete_key_v3d_exec (bContext *C, wmOperator *op) for (fcu= act->curves.first; fcu; fcu= fcn) { fcn= fcu->next; - success+= delete_keyframe(id, NULL, NULL, fcu->rna_path, fcu->array_index, cfra, 0); + success+= delete_keyframe(op->reports, id, NULL, NULL, fcu->rna_path, fcu->array_index, cfra, 0); } } @@ -1349,7 +1367,7 @@ static int insert_key_button_exec (bContext *C, wmOperator *op) { Main *bmain= CTX_data_main(C); Scene *scene= CTX_data_scene(C); - PointerRNA ptr; + PointerRNA ptr= {{NULL}}; PropertyRNA *prop= NULL; char *path; float cfra= (float)CFRA; // XXX for now, don't bother about all the yucky offset crap @@ -1361,10 +1379,9 @@ static int insert_key_button_exec (bContext *C, wmOperator *op) flag = ANIM_get_keyframing_flags(scene, 1); /* try to insert keyframe using property retrieved from UI */ - memset(&ptr, 0, sizeof(PointerRNA)); - uiAnimContextProperty(C, &ptr, &prop, &index); + uiContextActiveProperty(C, &ptr, &prop, &index); - if ((ptr.data && prop) && RNA_property_animateable(&ptr, prop)) { + if ((ptr.id.data && ptr.data && prop) && RNA_property_animateable(&ptr, prop)) { path= RNA_path_from_ID_to_property(&ptr, prop); if (path) { @@ -1378,7 +1395,7 @@ static int insert_key_button_exec (bContext *C, wmOperator *op) length= 1; for (a=0; a<length; a++) - success+= insert_keyframe(ptr.id.data, NULL, NULL, path, index+a, cfra, flag); + success+= insert_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index+a, cfra, flag); MEM_freeN(path); } @@ -1387,7 +1404,7 @@ static int insert_key_button_exec (bContext *C, wmOperator *op) NlaStrip *strip= (NlaStrip *)ptr.data; FCurve *fcu= list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), flag); - success+= insert_keyframe_direct(ptr, prop, fcu, cfra, 0); + success+= insert_keyframe_direct(op->reports, ptr, prop, fcu, cfra, 0); } else { if (G.f & G_DEBUG) @@ -1396,8 +1413,8 @@ static int insert_key_button_exec (bContext *C, wmOperator *op) } } else if (G.f & G_DEBUG) { - printf("ptr.data = %p, prop = %p,", ptr.data, prop); - if(prop) + printf("ptr.data = %p, prop = %p,", (void *)ptr.data, (void *)prop); + if (prop) printf("animateable = %d \n", RNA_property_animateable(&ptr, prop)); else printf("animateable = NULL \n"); @@ -1405,6 +1422,8 @@ static int insert_key_button_exec (bContext *C, wmOperator *op) if (success) { /* send updates */ + uiContextAnimUpdate(C); + DAG_ids_flush_update(bmain, 0); /* send notifiers that keyframes have been changed */ @@ -1437,7 +1456,7 @@ static int delete_key_button_exec (bContext *C, wmOperator *op) { Main *bmain= CTX_data_main(C); Scene *scene= CTX_data_scene(C); - PointerRNA ptr; + PointerRNA ptr= {{NULL}}; PropertyRNA *prop= NULL; char *path; float cfra= (float)CFRA; // XXX for now, don't bother about all the yucky offset crap @@ -1445,24 +1464,23 @@ static int delete_key_button_exec (bContext *C, wmOperator *op) int a, index, length, all= RNA_boolean_get(op->ptr, "all"); /* try to insert keyframe using property retrieved from UI */ - memset(&ptr, 0, sizeof(PointerRNA)); - uiAnimContextProperty(C, &ptr, &prop, &index); + uiContextActiveProperty(C, &ptr, &prop, &index); - if (ptr.data && prop) { + if (ptr.id.data && ptr.data && prop) { path= RNA_path_from_ID_to_property(&ptr, prop); if (path) { if (all) { length= RNA_property_array_length(&ptr, prop); - if(length) index= 0; + if (length) index= 0; else length= 1; } else length= 1; for (a=0; a<length; a++) - success+= delete_keyframe(ptr.id.data, NULL, NULL, path, index+a, cfra, 0); + success+= delete_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index+a, cfra, 0); MEM_freeN(path); } @@ -1470,12 +1488,14 @@ static int delete_key_button_exec (bContext *C, wmOperator *op) printf("Button Delete-Key: no path to property \n"); } else if (G.f & G_DEBUG) { - printf("ptr.data = %p, prop = %p \n", ptr.data, prop); + printf("ptr.data = %p, prop = %p \n", (void *)ptr.data, (void *)prop); } if (success) { /* send updates */ + uiContextAnimUpdate(C); + DAG_ids_flush_update(bmain, 0); /* send notifiers that keyframes have been changed */ @@ -1558,7 +1578,7 @@ short fcurve_frame_has_keyframe (FCurve *fcu, float frame, short filter) /* 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... */ -short action_frame_has_keyframe (bAction *act, float frame, short filter) +static short action_frame_has_keyframe (bAction *act, float frame, short filter) { FCurve *fcu; @@ -1586,7 +1606,7 @@ short action_frame_has_keyframe (bAction *act, float frame, short filter) } /* Checks whether an Object has a keyframe for a given frame */ -short object_frame_has_keyframe (Object *ob, float frame, short filter) +static short object_frame_has_keyframe (Object *ob, float frame, short filter) { /* error checking */ if (ob == NULL) diff --git a/source/blender/editors/animation/keyingsets.c b/source/blender/editors/animation/keyingsets.c index ab236de9ac5..d71c494705e 100644 --- a/source/blender/editors/animation/keyingsets.c +++ b/source/blender/editors/animation/keyingsets.c @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -38,6 +38,7 @@ #include "BLI_blenlib.h" #include "BLI_math.h" #include "BLI_dynstr.h" +#include "BLI_utildefines.h" #include "DNA_anim_types.h" #include "DNA_scene_types.h" @@ -59,6 +60,7 @@ #include "RNA_access.h" #include "RNA_define.h" +#include "RNA_enum_types.h" #include "anim_intern.h" @@ -107,7 +109,7 @@ static int keyingset_poll_activePath_edit (bContext *C) /* Add a Default (Empty) Keying Set ------------------------- */ -static int add_default_keyingset_exec (bContext *C, wmOperator *op) +static int add_default_keyingset_exec (bContext *C, wmOperator *UNUSED(op)) { Scene *scene= CTX_data_scene(C); short flag=0, keyingflag=0; @@ -286,7 +288,7 @@ static int add_keyingset_button_exec (bContext *C, wmOperator *op) Scene *scene= CTX_data_scene(C); KeyingSet *ks = NULL; PropertyRNA *prop= NULL; - PointerRNA ptr; + PointerRNA ptr= {{NULL}}; char *path = NULL; short success= 0; int index=0, pflag=0; @@ -306,7 +308,7 @@ static int add_keyingset_button_exec (bContext *C, wmOperator *op) keyingflag |= ANIM_get_keyframing_flags(scene, 0); - if (IS_AUTOKEY_FLAG(XYZ2RGB)) + if (IS_AUTOKEY_FLAG(scene, XYZ2RGB)) keyingflag |= INSERTKEY_XYZ2RGB; /* call the API func, and set the active keyingset index */ @@ -322,11 +324,10 @@ static int add_keyingset_button_exec (bContext *C, wmOperator *op) ks= BLI_findlink(&scene->keyingsets, scene->active_keyingset-1); /* try to add to keyingset using property retrieved from UI */ - memset(&ptr, 0, sizeof(PointerRNA)); - uiAnimContextProperty(C, &ptr, &prop, &index); + uiContextActiveProperty(C, &ptr, &prop, &index); /* check if property is able to be added */ - if (ptr.data && prop && RNA_property_animateable(&ptr, prop)) { + if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) { path= RNA_path_from_ID_to_property(&ptr, prop); if (path) { @@ -387,7 +388,7 @@ static int remove_keyingset_button_exec (bContext *C, wmOperator *op) Scene *scene= CTX_data_scene(C); KeyingSet *ks = NULL; PropertyRNA *prop= NULL; - PointerRNA ptr; + PointerRNA ptr= {{NULL}}; char *path = NULL; short success= 0; int index=0; @@ -408,10 +409,9 @@ static int remove_keyingset_button_exec (bContext *C, wmOperator *op) ks= BLI_findlink(&scene->keyingsets, scene->active_keyingset-1); /* try to add to keyingset using property retrieved from UI */ - memset(&ptr, 0, sizeof(PointerRNA)); - uiAnimContextProperty(C, &ptr, &prop, &index); + uiContextActiveProperty(C, &ptr, &prop, &index); - if (ptr.data && prop) { + if (ptr.id.data && ptr.data && prop) { path= RNA_path_from_ID_to_property(&ptr, prop); if (path) { @@ -419,12 +419,9 @@ static int remove_keyingset_button_exec (bContext *C, wmOperator *op) /* try to find a path matching this description */ ksp= BKE_keyingset_find_path(ks, ptr.id.data, ks->name, path, index, KSP_GROUP_KSNAME); - + if (ksp) { - /* just free it... */ - MEM_freeN(ksp->rna_path); - BLI_freelinkN(&ks->paths, ksp); - + BKE_keyingset_free_path(ks, ksp); success= 1; } @@ -464,7 +461,7 @@ void ANIM_OT_keyingset_button_remove (wmOperatorType *ot) /* Change Active KeyingSet Operator ------------------------ */ /* This operator checks if a menu should be shown for choosing the KeyingSet to make the active one */ -static int keyingset_active_menu_invoke (bContext *C, wmOperator *op, wmEvent *event) +static int keyingset_active_menu_invoke (bContext *C, wmOperator *op, wmEvent *UNUSED(event)) { /* call the menu, which will call this operator again, hence the cancelled */ ANIM_keying_sets_menu_setup(C, op->type->name, "ANIM_OT_keying_set_active_set"); @@ -503,7 +500,7 @@ void ANIM_OT_keying_set_active_set (wmOperatorType *ot) ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; /* keyingset to use - * - here the type is int not enum, since many of the indicies here are determined dynamically + * - here the type is int not enum, since many of the indices here are determined dynamically */ RNA_def_int(ot->srna, "type", 0, INT_MIN, INT_MAX, "Keying Set Number", "Index (determined internally) of the Keying Set to use", 0, 1); } @@ -512,7 +509,7 @@ void ANIM_OT_keying_set_active_set (wmOperatorType *ot) /* REGISTERED KEYING SETS */ /* Keying Set Type Info declarations */ -ListBase keyingset_type_infos = {NULL, NULL}; +static ListBase keyingset_type_infos = {NULL, NULL}; /* Built-In Keying Sets (referencing type infos)*/ ListBase builtin_keyingsets = {NULL, NULL}; @@ -558,7 +555,7 @@ KeyingSet *ANIM_builtin_keyingset_get_named (KeyingSet *prevKS, const char name[ /* --------------- */ /* Add the given KeyingSetInfo to the list of type infos, and create an appropriate builtin set too */ -void ANIM_keyingset_info_register (const bContext *C, KeyingSetInfo *ksi) +void ANIM_keyingset_info_register (KeyingSetInfo *ksi) { KeyingSet *ks; @@ -605,7 +602,7 @@ void ANIM_keyingset_info_unregister (const bContext *C, KeyingSetInfo *ksi) /* --------------- */ -void ANIM_keyingset_infos_exit () +void ANIM_keyingset_infos_exit (void) { KeyingSetInfo *ksi, *next; @@ -676,10 +673,86 @@ int ANIM_scene_get_keyingset_index (Scene *scene, KeyingSet *ks) return 0; } +/* Get Keying Set to use for Auto-Keyframing some transforms */ +KeyingSet *ANIM_get_keyingset_for_autokeying(Scene *scene, const char *tranformKSName) +{ + /* get KeyingSet to use + * - use the active KeyingSet if defined (and user wants to use it for all autokeying), + * or otherwise key transforms only + */ + if (IS_AUTOKEY_FLAG(scene, ONLYKEYINGSET) && (scene->active_keyingset)) + return ANIM_scene_get_active_keyingset(scene); + else if (IS_AUTOKEY_FLAG(scene, INSERTAVAIL)) + return ANIM_builtin_keyingset_get_named(NULL, "Available"); + else + return ANIM_builtin_keyingset_get_named(NULL, tranformKSName); +} + /* Menu of All Keying Sets ----------------------------- */ +/* Dynamically populate an enum of Keying Sets */ +EnumPropertyItem *ANIM_keying_sets_enum_itemf (bContext *C, PointerRNA *UNUSED(ptr), int *free) +{ + Scene *scene = CTX_data_scene(C); + KeyingSet *ks; + EnumPropertyItem *item= NULL, item_tmp= {0}; + int totitem= 0; + int i= 0; + + if (C == NULL) { + return DummyRNA_DEFAULT_items; + } + + /* active Keying Set + * - only include entry if it exists + */ + if (scene->active_keyingset) { + /* active Keying Set */ + item_tmp.identifier= item_tmp.name= "Active Keying Set"; + item_tmp.value= i++; + RNA_enum_item_add(&item, &totitem, &item_tmp); + + /* separator */ + RNA_enum_item_add_separator(&item, &totitem); + } + else + i++; + + /* user-defined Keying Sets + * - these are listed in the order in which they were defined for the active scene + */ + if (scene->keyingsets.first) { + for (ks= scene->keyingsets.first; ks; ks= ks->next) { + if (ANIM_keyingset_context_ok_poll(C, ks)) { + item_tmp.identifier= item_tmp.name= ks->name; + item_tmp.value= i++; + RNA_enum_item_add(&item, &totitem, &item_tmp); + } + } + + /* separator */ + RNA_enum_item_add_separator(&item, &totitem); + } + + /* builtin Keying Sets */ + i= -1; + for (ks= builtin_keyingsets.first; ks; ks= ks->next) { + /* only show KeyingSet if context is suitable */ + if (ANIM_keyingset_context_ok_poll(C, ks)) { + item_tmp.identifier= item_tmp.name= ks->name; + item_tmp.value= i--; + RNA_enum_item_add(&item, &totitem, &item_tmp); + } + } + + RNA_enum_item_end(&item, &totitem); + *free= 1; + + return item; +} + /* Create (and show) a menu containing all the Keying Sets which can be used in the current context */ -void ANIM_keying_sets_menu_setup (bContext *C, char title[], char op_name[]) +void ANIM_keying_sets_menu_setup (bContext *C, const char title[], const char op_name[]) { Scene *scene= CTX_data_scene(C); KeyingSet *ks; @@ -687,14 +760,14 @@ void ANIM_keying_sets_menu_setup (bContext *C, char title[], char op_name[]) uiLayout *layout; int i = 0; - pup= uiPupMenuBegin(C, title, 0); + pup= uiPupMenuBegin(C, title, ICON_NULL); layout= uiPupMenuLayout(pup); /* active Keying Set * - only include entry if it exists */ if (scene->active_keyingset) { - uiItemIntO(layout, "Active Keying Set", 0, op_name, "type", i++); + uiItemIntO(layout, "Active Keying Set", ICON_NULL, op_name, "type", i++); uiItemS(layout); } else @@ -706,7 +779,7 @@ void ANIM_keying_sets_menu_setup (bContext *C, char title[], char op_name[]) if (scene->keyingsets.first) { for (ks= scene->keyingsets.first; ks; ks= ks->next) { if (ANIM_keyingset_context_ok_poll(C, ks)) - uiItemIntO(layout, ks->name, 0, op_name, "type", i++); + uiItemIntO(layout, ks->name, ICON_NULL, op_name, "type", i++); } uiItemS(layout); } @@ -716,7 +789,7 @@ void ANIM_keying_sets_menu_setup (bContext *C, char title[], char op_name[]) for (ks= builtin_keyingsets.first; ks; ks= ks->next) { /* only show KeyingSet if context is suitable */ if (ANIM_keyingset_context_ok_poll(C, ks)) - uiItemIntO(layout, ks->name, 0, op_name, "type", i--); + uiItemIntO(layout, ks->name, ICON_NULL, op_name, "type", i--); } uiPupMenuEnd(C, pup); @@ -805,6 +878,7 @@ void ANIM_relative_keyingset_add_source (ListBase *dsources, ID *id, StructRNA * int ANIM_apply_keyingset (bContext *C, ListBase *dsources, bAction *act, KeyingSet *ks, short mode, float cfra) { Scene *scene= CTX_data_scene(C); + ReportList *reports = CTX_wm_reports(C); KS_Path *ksp; int kflag=0, success= 0; char *groupname= NULL; @@ -863,6 +937,14 @@ int ANIM_apply_keyingset (bContext *C, ListBase *dsources, bAction *act, KeyingS int arraylen, i; short kflag2; + /* skip path if no ID pointer is specified */ + if (ksp->id == NULL) { + BKE_reportf(reports, RPT_WARNING, + "Skipping path in Keying Set, as it has no ID (KS = '%s', Path = '%s'[%d])", + ks->name, ksp->rna_path, ksp->array_index); + continue; + } + /* since keying settings can be defined on the paths too, extend the path before using it */ kflag2 = (kflag | ksp->keyingflag); @@ -900,26 +982,24 @@ int ANIM_apply_keyingset (bContext *C, ListBase *dsources, bAction *act, KeyingS for (; i < arraylen; i++) { /* action to take depends on mode */ if (mode == MODIFYKEY_MODE_INSERT) - success += insert_keyframe(ksp->id, act, groupname, ksp->rna_path, i, cfra, kflag2); + success += insert_keyframe(reports, ksp->id, act, groupname, ksp->rna_path, i, cfra, kflag2); else if (mode == MODIFYKEY_MODE_DELETE) - success += delete_keyframe(ksp->id, act, groupname, ksp->rna_path, i, cfra, kflag2); + success += delete_keyframe(reports, ksp->id, act, groupname, ksp->rna_path, i, cfra, kflag2); } /* set recalc-flags */ - if (ksp->id) { - switch (GS(ksp->id->name)) { - case ID_OB: /* Object (or Object-Related) Keyframes */ - { - Object *ob= (Object *)ksp->id; - - ob->recalc |= OB_RECALC_ALL; // XXX: only object transforms only? - } - break; + switch (GS(ksp->id->name)) { + case ID_OB: /* Object (or Object-Related) Keyframes */ + { + Object *ob= (Object *)ksp->id; + + ob->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME; // XXX: only object transforms only? } - - /* send notifiers for updates (this doesn't require context to work!) */ - WM_main_add_notifier(NC_ANIMATION|ND_KEYFRAME|NA_EDITED, NULL); + break; } + + /* send notifiers for updates (this doesn't require context to work!) */ + WM_main_add_notifier(NC_ANIMATION|ND_KEYFRAME|NA_EDITED, NULL); } /* return the number of channels successfully affected */ |