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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c48
-rw-r--r--source/blender/blenkernel/intern/ipo.c43
-rw-r--r--source/blender/blenloader/intern/readfile.c10
-rw-r--r--source/blender/editors/space_nla/nla_edit.c16
-rw-r--r--source/blender/makesdna/DNA_action_types.h3
-rw-r--r--source/blender/makesrna/intern/rna_action.c72
-rw-r--r--source/blender/makesrna/intern/rna_animation.c36
-rw-r--r--source/blender/makesrna/intern/rna_internal.h3
-rw-r--r--source/blender/makesrna/intern/rna_nla.c1
-rw-r--r--source/blender/makesrna/intern/rna_space.c29
10 files changed, 252 insertions, 9 deletions
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index 2708239a4c3..f7eaff475fa 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -1199,6 +1199,39 @@ static void animsys_evaluate_drivers (PointerRNA *ptr, AnimData *adt, float ctim
/* ***************************************** */
/* Actions Evaluation */
+/* strictly not necessary for actual "evaluation", but it is a useful safety check
+ * to reduce the amount of times that users end up having to "revive" wrongly-assigned
+ * actions
+ */
+static void action_idcode_patch_check (ID *id, bAction *act)
+{
+ int idcode = 0;
+
+ /* just in case */
+ if (ELEM(NULL, id, act))
+ return;
+ else
+ idcode = GS(id->name);
+
+ /* the actual checks... hopefully not too much of a performance hit in the long run... */
+ if (act->idroot == 0) {
+ /* use the current root if not set already (i.e. newly created actions and actions from 2.50-2.57 builds)
+ * - this has problems if there are 2 users, and the first one encountered is the invalid one
+ * in which case, the user will need to manually fix this (?)
+ */
+ act->idroot = idcode;
+ }
+ else if (act->idroot != idcode) {
+ /* only report this error if debug mode is enabled (to save performance everywhere else) */
+ if (G.f & G_DEBUG) {
+ printf("AnimSys Safety Check Failed: Action '%s' is not meant to be used from ID-Blocks of type %d such as '%s'\n",
+ act->id.name+2, idcode, id->name);
+ }
+ }
+}
+
+/* ----------------------------------------- */
+
/* Evaluate Action Group */
void animsys_evaluate_action_group (PointerRNA *ptr, bAction *act, bActionGroup *agrp, AnimMapper *remap, float ctime)
{
@@ -1208,6 +1241,8 @@ void animsys_evaluate_action_group (PointerRNA *ptr, bAction *act, bActionGroup
if ELEM(NULL, act, agrp) return;
if ((remap) && (remap->target != act)) remap= NULL;
+ action_idcode_patch_check(ptr->id.data, act);
+
/* if group is muted, don't evaluated any of the F-Curve */
if (agrp->flag & AGRP_MUTED)
return;
@@ -1231,6 +1266,8 @@ void animsys_evaluate_action (PointerRNA *ptr, bAction *act, AnimMapper *remap,
if (act == NULL) return;
if ((remap) && (remap->target != act)) remap= NULL;
+ action_idcode_patch_check(ptr->id.data, act);
+
/* calculate then execute each curve */
animsys_evaluate_fcurves(ptr, &act->curves, remap, ctime);
}
@@ -1630,6 +1667,17 @@ static void nlastrip_evaluate_actionclip (PointerRNA *ptr, ListBase *channels, L
FCurve *fcu;
float evaltime;
+ /* sanity checks for action */
+ if (strip == NULL)
+ return;
+
+ if (strip->act == NULL) {
+ printf("NLA-Strip Eval Error: Strip '%s' has no Action\n", strip->name);
+ return;
+ }
+
+ action_idcode_patch_check(ptr->id.data, strip->act);
+
/* join this strip's modifiers to the parent's modifiers (own modifiers first) */
nlaeval_fmodifiers_join_stacks(&tmp_modifiers, &strip->modifiers, modifiers);
diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c
index 08e0ad4f3ff..689e17958fe 100644
--- a/source/blender/blenkernel/intern/ipo.c
+++ b/source/blender/blenkernel/intern/ipo.c
@@ -1372,7 +1372,7 @@ static void icu_to_fcurves (ID *id, ListBase *groups, ListBase *list, IpoCurve *
* This does not assume that any ID or AnimData uses it, but does assume that
* it is given two lists, which it will perform driver/animation-data separation.
*/
-static void ipo_to_animato (ID *id, Ipo *ipo, char actname[], char constname[], Sequence * seq, ListBase *animgroups, ListBase *anim, ListBase *drivers)
+static void ipo_to_animato (ID *id, Ipo *ipo, char actname[], char constname[], Sequence *seq, ListBase *animgroups, ListBase *anim, ListBase *drivers)
{
IpoCurve *icu;
@@ -1804,6 +1804,10 @@ void do_versions_ipos_to_animato(Main *main)
BLI_freelinkN(&ob->constraintChannels, conchan);
}
}
+
+ /* object's action will always be object-rooted */
+ if (adt->action)
+ adt->action->idroot = ID_OB;
}
/* shapekeys */
@@ -1822,6 +1826,10 @@ void do_versions_ipos_to_animato(Main *main)
/* Convert Shapekey data... */
ipo_to_animdata(id, key->ipo, NULL, NULL, NULL);
+
+ if (adt->action)
+ adt->action->idroot = key->ipo->blocktype;
+
key->ipo->id.us--;
key->ipo= NULL;
}
@@ -1840,6 +1848,10 @@ void do_versions_ipos_to_animato(Main *main)
/* Convert Material data... */
ipo_to_animdata(id, ma->ipo, NULL, NULL, NULL);
+
+ if (adt->action)
+ adt->action->idroot = ma->ipo->blocktype;
+
ma->ipo->id.us--;
ma->ipo= NULL;
}
@@ -1858,6 +1870,10 @@ void do_versions_ipos_to_animato(Main *main)
/* Convert World data... */
ipo_to_animdata(id, wo->ipo, NULL, NULL, NULL);
+
+ if (adt->action)
+ adt->action->idroot = wo->ipo->blocktype;
+
wo->ipo->id.us--;
wo->ipo= NULL;
}
@@ -1904,6 +1920,10 @@ void do_versions_ipos_to_animato(Main *main)
/* convert IPO */
ipo_to_animdata((ID *)scene, seq->ipo, NULL, NULL, seq);
+
+ if (adt->action)
+ adt->action->idroot = ID_SCE; /* scene-rooted */
+
seq->ipo->id.us--;
seq->ipo = NULL;
}
@@ -1925,6 +1945,10 @@ void do_versions_ipos_to_animato(Main *main)
/* Convert Texture data... */
ipo_to_animdata(id, te->ipo, NULL, NULL, NULL);
+
+ if (adt->action)
+ adt->action->idroot = te->ipo->blocktype;
+
te->ipo->id.us--;
te->ipo= NULL;
}
@@ -1943,6 +1967,10 @@ void do_versions_ipos_to_animato(Main *main)
/* Convert Camera data... */
ipo_to_animdata(id, ca->ipo, NULL, NULL, NULL);
+
+ if (adt->action)
+ adt->action->idroot = ca->ipo->blocktype;
+
ca->ipo->id.us--;
ca->ipo= NULL;
}
@@ -1961,6 +1989,10 @@ void do_versions_ipos_to_animato(Main *main)
/* Convert Lamp data... */
ipo_to_animdata(id, la->ipo, NULL, NULL, NULL);
+
+ if (adt->action)
+ adt->action->idroot = la->ipo->blocktype;
+
la->ipo->id.us--;
la->ipo= NULL;
}
@@ -1979,6 +2011,10 @@ void do_versions_ipos_to_animato(Main *main)
/* Convert Curve data... */
ipo_to_animdata(id, cu->ipo, NULL, NULL, NULL);
+
+ if (adt->action)
+ adt->action->idroot = cu->ipo->blocktype;
+
cu->ipo->id.us--;
cu->ipo= NULL;
}
@@ -2001,6 +2037,10 @@ void do_versions_ipos_to_animato(Main *main)
if (G.f & G_DEBUG) printf("\tconverting action %s \n", id->name+2);
+ /* if old action, it will be object-only... */
+ if (act->chanbase.first)
+ act->idroot = ID_OB;
+
/* be careful! some of the actions we encounter will be converted ones... */
action_to_animato(NULL, act, &act->groups, &act->curves, &drivers);
}
@@ -2018,6 +2058,7 @@ void do_versions_ipos_to_animato(Main *main)
/* add a new action for this, and convert all data into that action */
new_act= add_empty_action("ConvIPO_Action"); // XXX need a better name...
ipo_to_animato(NULL, ipo, NULL, NULL, NULL, NULL, &new_act->curves, &drivers);
+ new_act->idroot = ipo->blocktype;
}
/* clear fake-users, and set user-count to zero to make sure it is cleared on file-save */
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 4ff65aeb213..a87d993bc15 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -1863,6 +1863,10 @@ static void lib_link_nladata_strips(FileData *fd, ID *id, ListBase *list)
/* reassign the counted-reference to action */
strip->act = newlibadr_us(fd, id->lib, strip->act);
+
+ /* fix action id-root (i.e. if it comes from a pre 2.57 .blend file) */
+ if ((strip->act) && (strip->act->idroot == 0))
+ strip->act->idroot = GS(id->name);
}
}
@@ -1956,6 +1960,12 @@ static void lib_link_animdata(FileData *fd, ID *id, AnimData *adt)
adt->action= newlibadr_us(fd, id->lib, adt->action);
adt->tmpact= newlibadr_us(fd, id->lib, adt->tmpact);
+ /* fix action id-roots (i.e. if they come from a pre 2.57 .blend file) */
+ if ((adt->action) && (adt->action->idroot == 0))
+ adt->action->idroot = GS(id->name);
+ if ((adt->tmpact) && (adt->tmpact->idroot == 0))
+ adt->tmpact->idroot = GS(id->name);
+
/* link drivers */
lib_link_fcurves(fd, id, &adt->drivers);
diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c
index 0bcf84c1870..77c91b28a63 100644
--- a/source/blender/editors/space_nla/nla_edit.c
+++ b/source/blender/editors/space_nla/nla_edit.c
@@ -271,6 +271,12 @@ static int nlaedit_add_actionclip_exec (bContext *C, wmOperator *op)
//printf("Add strip - actname = '%s' \n", actname);
return OPERATOR_CANCELLED;
}
+ else if (act->idroot == 0) {
+ /* hopefully in this case (i.e. library of userless actions), the user knows what they're doing... */
+ BKE_reportf(op->reports, RPT_WARNING,
+ "Action '%s' does not specify what datablocks it can be used on. Try setting the 'ID Root Type' setting from the Datablocks Editor for this Action to avoid future problems",
+ act->id.name+2);
+ }
/* get a list of the editable tracks being shown in the NLA
* - this is limited to active ones for now, but could be expanded to
@@ -289,6 +295,16 @@ static int nlaedit_add_actionclip_exec (bContext *C, wmOperator *op)
AnimData *adt= ale->adt;
NlaStrip *strip= NULL;
+ /* sanity check: only apply actions of the right type for this ID
+ * NOTE: in the case that this hasn't been set, we've already warned the user about this already
+ */
+ if ((act->idroot) && (act->idroot != GS(ale->id->name))) {
+ BKE_reportf(op->reports, RPT_ERROR,
+ "Couldn't add action '%s' as it cannot be used relative to ID-blocks of type '%s'",
+ act->id.name+2, ale->id->name);
+ continue;
+ }
+
/* create a new strip, and offset it to start on the current frame */
strip= add_nlastrip(act);
diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h
index 412b9bc56f6..0716d1ddbf2 100644
--- a/source/blender/makesdna/DNA_action_types.h
+++ b/source/blender/makesdna/DNA_action_types.h
@@ -487,6 +487,9 @@ typedef struct bAction {
int flag; /* settings for this action */
int active_marker; /* index of the active marker */
+
+ int idroot; /* type of ID-blocks that action can be assigned to (if 0, will be set to whatever ID first evaluates it) */
+ int pad;
} bAction;
diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c
index 418451801ca..7fdb96fda6e 100644
--- a/source/blender/makesrna/intern/rna_action.c
+++ b/source/blender/makesrna/intern/rna_action.c
@@ -30,6 +30,7 @@
#include <stdlib.h>
#include "RNA_define.h"
+#include "RNA_enum_types.h"
#include "rna_internal.h"
@@ -194,6 +195,56 @@ static void rna_Action_frame_range_get(PointerRNA *ptr,float *values)
calc_action_range(ptr->id.data, values, values+1, 1);
}
+
+/* used to check if an action (value pointer) is suitable to be assigned to the ID-block that is ptr */
+int rna_Action_id_poll(PointerRNA *ptr, PointerRNA value)
+{
+ ID *srcId = (ID *)ptr->id.data;
+ bAction *act = (bAction *)value.id.data;
+
+ if (act) {
+ /* there can still be actions that will have undefined id-root
+ * (i.e. floating "action-library" members) which we will not
+ * be able to resolve an idroot for automatically, so let these through
+ */
+ if (act->idroot == 0)
+ return 1;
+ else if (srcId)
+ return GS(srcId->name) == act->idroot;
+ }
+
+ return 0;
+}
+
+/* used to check if an action (value pointer) can be assigned to Action Editor given current mode */
+int rna_Action_actedit_assign_poll(PointerRNA *ptr, PointerRNA value)
+{
+ SpaceAction *saction = (SpaceAction *)ptr->data;
+ bAction *act = (bAction *)value.id.data;
+
+ if (act) {
+ /* there can still be actions that will have undefined id-root
+ * (i.e. floating "action-library" members) which we will not
+ * be able to resolve an idroot for automatically, so let these through
+ */
+ if (act->idroot == 0)
+ return 1;
+
+ if (saction) {
+ if (saction->mode == SACTCONT_ACTION) {
+ /* this is only Object-level for now... */
+ return act->idroot == ID_OB;
+ }
+ else if (saction->mode == SACTCONT_SHAPEKEY) {
+ /* obviously shapekeys only */
+ return act->idroot == ID_KE;
+ }
+ }
+ }
+
+ return 0;
+}
+
#else
static void rna_def_dopesheet(BlenderRNA *brna)
@@ -515,34 +566,43 @@ static void rna_def_action(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
-
+
srna= RNA_def_struct(brna, "Action", "ID");
RNA_def_struct_sdna(srna, "bAction");
RNA_def_struct_ui_text(srna, "Action", "A collection of F-Curves for animation");
RNA_def_struct_ui_icon(srna, ICON_ACTION);
-
+
+ /* collections */
prop= RNA_def_property(srna, "fcurves", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "curves", NULL);
RNA_def_property_struct_type(prop, "FCurve");
RNA_def_property_ui_text(prop, "F-Curves", "The individual F-Curves that make up the Action");
rna_def_action_fcurves(brna, prop);
-
+
prop= RNA_def_property(srna, "groups", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "groups", NULL);
RNA_def_property_struct_type(prop, "ActionGroup");
RNA_def_property_ui_text(prop, "Groups", "Convenient groupings of F-Curves");
rna_def_action_groups(brna, prop);
-
+
prop= RNA_def_property(srna, "pose_markers", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "markers", NULL);
RNA_def_property_struct_type(prop, "TimelineMarker");
RNA_def_property_ui_text(prop, "Pose Markers", "Markers specific to this Action, for labeling poses");
rna_def_action_pose_markers(brna, prop);
-
+
+ /* properties */
prop= RNA_def_float_vector(srna, "frame_range" , 2 , NULL , 0, 0, "Frame Range" , "The final frame range of all fcurves within this action" , 0 , 0);
RNA_def_property_float_funcs(prop, "rna_Action_frame_range_get" , NULL, NULL);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
-
+
+ /* special "type" limiter - should not really be edited in general, but is still available/editable in 'emergencies' */
+ prop= RNA_def_property(srna, "id_root", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "idroot");
+ RNA_def_property_enum_items(prop, id_type_items);
+ RNA_def_property_ui_text(prop, "ID Root Type", "Type of ID-block that action can be used on. DO NOT CHANGE UNLESS YOU KNOW WHAT YOU'RE DOING");
+
+ /* API calls */
RNA_api_action(srna);
}
diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c
index 17d2e27c462..8e210a7a4cb 100644
--- a/source/blender/makesrna/intern/rna_animation.c
+++ b/source/blender/makesrna/intern/rna_animation.c
@@ -70,6 +70,41 @@ static int rna_AnimData_action_editable(PointerRNA *ptr)
return 1;
}
+static void rna_AnimData_action_set(PointerRNA *ptr, PointerRNA value)
+{
+ ID *ownerId = (ID *)ptr->id.data;
+ AnimData *adt = (AnimData *)ptr->data;
+
+ /* assume that AnimData's action can in fact be edited... */
+ if ((value.data) && (ownerId)) {
+ bAction *act = (bAction *)value.data;
+
+ /* action must have same type as owner */
+ if (ownerId) {
+ if (ELEM(act->idroot, 0, GS(ownerId->name))) {
+ /* can set */
+ adt->action = act;
+ }
+ else {
+ /* cannot set */
+ printf("ERROR: Couldn't set Action '%s' onto ID '%s', as it doesn't have suitably rooted paths for this purpose\n",
+ act->id.name+2, ownerId->name);
+ }
+ }
+ else {
+ /* cannot tell if we can set, so let's just be generous... */
+ printf("Warning: Set Action '%s' onto AnimData block with an unknown ID-owner. May have attached invalid data\n",
+ act->id.name+2);
+
+ adt->action = act;
+ }
+ }
+ else {
+ /* just clearing the action... */
+ adt->action = NULL;
+ }
+}
+
/* ****************************** */
/* wrapper for poll callback */
@@ -739,6 +774,7 @@ void rna_def_animdata(BlenderRNA *brna)
/* Active Action */
prop= RNA_def_property(srna, "action", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_EDITABLE); /* this flag as well as the dynamic test must be defined for this to be editable... */
+ RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Action_id_poll");
RNA_def_property_editable_func(prop, "rna_AnimData_action_editable");
RNA_def_property_ui_text(prop, "Action", "Active Action for this datablock");
RNA_def_property_update(prop, NC_ANIMATION, NULL); /* this will do? */
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index 4dc98ceb0a4..1d060c8a362 100644
--- a/source/blender/makesrna/intern/rna_internal.h
+++ b/source/blender/makesrna/intern/rna_internal.h
@@ -222,6 +222,9 @@ int rna_Curve_object_poll(struct PointerRNA *ptr, struct PointerRNA value);
int rna_Lattice_object_poll(struct PointerRNA *ptr, struct PointerRNA value);
int rna_Mesh_object_poll(struct PointerRNA *ptr, struct PointerRNA value);
+/* basic poll functions for actions (to prevent actions getting set in wrong places) */
+int rna_Action_id_poll(struct PointerRNA *ptr, struct PointerRNA value);
+int rna_Action_actedit_assign_poll(struct PointerRNA *ptr, struct PointerRNA value);
char *rna_TextureSlot_path(struct PointerRNA *ptr);
diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c
index 09837579949..9bf5f53f8b7 100644
--- a/source/blender/makesrna/intern/rna_nla.c
+++ b/source/blender/makesrna/intern/rna_nla.c
@@ -426,6 +426,7 @@ static void rna_def_nlastrip(BlenderRNA *brna)
/* Action */
prop= RNA_def_property(srna, "action", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "act");
+ RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Action_id_poll");
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Action", "Action referenced by this strip");
RNA_def_property_update(prop, NC_ANIMATION|ND_NLA, NULL); /* this will do? */
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 3d9d8a8e9f4..52fae14a023 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -644,7 +644,32 @@ static void rna_ConsoleLine_cursor_index_range(PointerRNA *ptr, int *min, int *m
static void rna_SpaceDopeSheetEditor_action_set(PointerRNA *ptr, PointerRNA value)
{
SpaceAction *saction= (SpaceAction*)(ptr->data);
- saction->action= value.data;
+ bAction *act = (bAction*)value.data;
+
+ if ((act == NULL) || (act->idroot == 0)) {
+ /* just set if we're clearing the action or if the action is "amorphous" still */
+ saction->action= act;
+ }
+ else {
+ /* action to set must strictly meet the mode criteria... */
+ if (saction->mode == SACTCONT_ACTION) {
+ /* currently, this is "object-level" only, until we have some way of specifying this */
+ if (act->idroot == ID_OB)
+ saction->action = act;
+ else
+ printf("ERROR: cannot assign Action '%s' to Action Editor, as action is not object-level animation\n", act->id.name+2);
+ }
+ else if (saction->mode == SACTCONT_SHAPEKEY) {
+ /* as the name says, "shapekey-level" only... */
+ if (act->idroot == ID_KE)
+ saction->action = act;
+ else
+ printf("ERROR: cannot assign Action '%s' to Shape Key Editor, as action doesn't animate Shape Keys\n", act->id.name+2);
+ }
+ else {
+ printf("ACK: who's trying to set an action while not in a mode displaying a single Action only?\n");
+ }
+ }
}
static void rna_SpaceDopeSheetEditor_action_update(Main *bmain, Scene *scene, PointerRNA *ptr)
@@ -1771,7 +1796,7 @@ static void rna_def_space_dopesheet(BlenderRNA *brna)
/* data */
prop= RNA_def_property(srna, "action", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_pointer_funcs(prop, NULL, "rna_SpaceDopeSheetEditor_action_set", NULL, NULL);
+ RNA_def_property_pointer_funcs(prop, NULL, "rna_SpaceDopeSheetEditor_action_set", NULL, "rna_Action_actedit_assign_poll");
RNA_def_property_ui_text(prop, "Action", "Action displayed and edited in this space");
RNA_def_property_update(prop, NC_ANIMATION|ND_KEYFRAME|NA_EDITED, "rna_SpaceDopeSheetEditor_action_update");