This was returning an empty allocated string, however almost all callers checked if the return value was NULL before freeing, making for misunderstandings on the intended use of this function. BCAnimationSampler::initialize_curves for example detected the f-curves animation type to 'bone' based on a non-NULL return value which never failed. Also fixes two leaks where the the result of BLI_str_quoted_substrN wasn't freed.
663 lines
21 KiB
C++
663 lines
21 KiB
C++
/*
|
|
* 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) 2008 Blender Foundation.
|
|
* All rights reserved.
|
|
*/
|
|
|
|
#include <algorithm> /* std::find */
|
|
#include <map>
|
|
#include <vector>
|
|
|
|
#include "BCAnimationCurve.h"
|
|
#include "BCAnimationSampler.h"
|
|
#include "BCMath.h"
|
|
#include "ExportSettings.h"
|
|
#include "collada_utils.h"
|
|
|
|
#include "BKE_action.h"
|
|
#include "BKE_constraint.h"
|
|
#include "BKE_key.h"
|
|
#include "BKE_lib_id.h"
|
|
#include "BKE_main.h"
|
|
#include "BKE_material.h"
|
|
|
|
#include "BLI_listbase.h"
|
|
|
|
#include "DNA_anim_types.h"
|
|
#include "DNA_constraint_types.h"
|
|
#include "DNA_key_types.h"
|
|
#include "DNA_scene_types.h"
|
|
|
|
#include "ED_object.h"
|
|
|
|
static std::string EMPTY_STRING;
|
|
static BCAnimationCurveMap BCEmptyAnimationCurves;
|
|
|
|
BCAnimationSampler::BCAnimationSampler(BCExportSettings &export_settings, BCObjectSet &object_set)
|
|
: export_settings(export_settings)
|
|
{
|
|
BCObjectSet::iterator it;
|
|
for (it = object_set.begin(); it != object_set.end(); ++it) {
|
|
Object *ob = *it;
|
|
add_object(ob);
|
|
}
|
|
}
|
|
|
|
BCAnimationSampler::~BCAnimationSampler()
|
|
{
|
|
BCAnimationObjectMap::iterator it;
|
|
for (it = objects.begin(); it != objects.end(); ++it) {
|
|
BCAnimation *animation = it->second;
|
|
delete animation;
|
|
}
|
|
}
|
|
|
|
void BCAnimationSampler::add_object(Object *ob)
|
|
{
|
|
BlenderContext blender_context = export_settings.get_blender_context();
|
|
BCAnimation *animation = new BCAnimation(blender_context.get_context(), ob);
|
|
objects[ob] = animation;
|
|
|
|
initialize_keyframes(animation->frame_set, ob);
|
|
initialize_curves(animation->curve_map, ob);
|
|
}
|
|
|
|
BCAnimationCurveMap *BCAnimationSampler::get_curves(Object *ob)
|
|
{
|
|
BCAnimation &animation = *objects[ob];
|
|
if (animation.curve_map.empty()) {
|
|
initialize_curves(animation.curve_map, ob);
|
|
}
|
|
return &animation.curve_map;
|
|
}
|
|
|
|
static void get_sample_frames(BCFrameSet &sample_frames,
|
|
int sampling_rate,
|
|
bool keyframe_at_end,
|
|
Scene *scene)
|
|
{
|
|
sample_frames.clear();
|
|
|
|
if (sampling_rate < 1) {
|
|
return; /* no sample frames in this case */
|
|
}
|
|
|
|
float sfra = scene->r.sfra;
|
|
float efra = scene->r.efra;
|
|
|
|
int frame_index;
|
|
for (frame_index = nearbyint(sfra); frame_index < efra; frame_index += sampling_rate) {
|
|
sample_frames.insert(frame_index);
|
|
}
|
|
|
|
if (frame_index >= efra && keyframe_at_end) {
|
|
sample_frames.insert(efra);
|
|
}
|
|
}
|
|
|
|
static bool is_object_keyframe(Object *ob, int frame_index)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
static void add_keyframes_from(bAction *action, BCFrameSet &frameset)
|
|
{
|
|
if (action) {
|
|
FCurve *fcu = nullptr;
|
|
for (fcu = (FCurve *)action->curves.first; fcu; fcu = fcu->next) {
|
|
BezTriple *bezt = fcu->bezt;
|
|
for (int i = 0; i < fcu->totvert; bezt++, i++) {
|
|
int frame_index = nearbyint(bezt->vec[1][0]);
|
|
frameset.insert(frame_index);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void BCAnimationSampler::check_property_is_animated(
|
|
BCAnimation &animation, float *ref, float *val, std::string data_path, int length)
|
|
{
|
|
for (int array_index = 0; array_index < length; array_index++) {
|
|
if (!bc_in_range(ref[length], val[length], 0.00001)) {
|
|
BCCurveKey key(BC_ANIMATION_TYPE_OBJECT, data_path, array_index);
|
|
BCAnimationCurveMap::iterator it = animation.curve_map.find(key);
|
|
if (it == animation.curve_map.end()) {
|
|
animation.curve_map[key] = new BCAnimationCurve(key, animation.get_reference());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void BCAnimationSampler::update_animation_curves(BCAnimation &animation,
|
|
BCSample &sample,
|
|
Object *ob,
|
|
int frame)
|
|
{
|
|
BCAnimationCurveMap::iterator it;
|
|
for (it = animation.curve_map.begin(); it != animation.curve_map.end(); ++it) {
|
|
BCAnimationCurve *curve = it->second;
|
|
if (curve->is_transform_curve()) {
|
|
curve->add_value_from_matrix(sample, frame);
|
|
}
|
|
else {
|
|
curve->add_value_from_rna(frame);
|
|
}
|
|
}
|
|
}
|
|
|
|
BCSample &BCAnimationSampler::sample_object(Object *ob, int frame_index, bool for_opensim)
|
|
{
|
|
BCSample &ob_sample = sample_data.add(ob, frame_index);
|
|
// if (export_settings.get_apply_global_orientation()) {
|
|
// const BCMatrix &global_transform = export_settings.get_global_transform();
|
|
// ob_sample.get_matrix(global_transform);
|
|
//}
|
|
|
|
if (ob->type == OB_ARMATURE) {
|
|
bPoseChannel *pchan;
|
|
for (pchan = (bPoseChannel *)ob->pose->chanbase.first; pchan; pchan = pchan->next) {
|
|
Bone *bone = pchan->bone;
|
|
Matrix bmat;
|
|
if (bc_bone_matrix_local_get(ob, bone, bmat, for_opensim)) {
|
|
|
|
ob_sample.add_bone_matrix(bone, bmat);
|
|
}
|
|
}
|
|
}
|
|
return ob_sample;
|
|
}
|
|
|
|
void BCAnimationSampler::sample_scene(BCExportSettings &export_settings, bool keyframe_at_end)
|
|
{
|
|
BlenderContext blender_context = export_settings.get_blender_context();
|
|
int sampling_rate = export_settings.get_sampling_rate();
|
|
bool for_opensim = export_settings.get_open_sim();
|
|
bool keep_keyframes = export_settings.get_keep_keyframes();
|
|
BC_export_animation_type export_animation_type = export_settings.get_export_animation_type();
|
|
|
|
Scene *scene = blender_context.get_scene();
|
|
BCFrameSet scene_sample_frames;
|
|
get_sample_frames(scene_sample_frames, sampling_rate, keyframe_at_end, scene);
|
|
BCFrameSet::iterator it;
|
|
|
|
int startframe = scene->r.sfra;
|
|
int endframe = scene->r.efra;
|
|
|
|
for (int frame_index = startframe; frame_index <= endframe; frame_index++) {
|
|
/* Loop over all frames and decide for each frame if sampling is necessary */
|
|
bool is_scene_sample_frame = false;
|
|
bool needs_update = true;
|
|
if (scene_sample_frames.find(frame_index) != scene_sample_frames.end()) {
|
|
bc_update_scene(blender_context, frame_index);
|
|
needs_update = false;
|
|
is_scene_sample_frame = true;
|
|
}
|
|
|
|
bool needs_sampling = is_scene_sample_frame || keep_keyframes ||
|
|
export_animation_type == BC_ANIMATION_EXPORT_KEYS;
|
|
if (!needs_sampling) {
|
|
continue;
|
|
}
|
|
|
|
BCAnimationObjectMap::iterator obit;
|
|
for (obit = objects.begin(); obit != objects.end(); ++obit) {
|
|
Object *ob = obit->first;
|
|
BCAnimation *animation = obit->second;
|
|
BCFrameSet &object_keyframes = animation->frame_set;
|
|
if (is_scene_sample_frame || object_keyframes.find(frame_index) != object_keyframes.end()) {
|
|
|
|
if (needs_update) {
|
|
bc_update_scene(blender_context, frame_index);
|
|
needs_update = false;
|
|
}
|
|
|
|
BCSample &sample = sample_object(ob, frame_index, for_opensim);
|
|
update_animation_curves(*animation, sample, ob, frame_index);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool BCAnimationSampler::is_animated_by_constraint(Object *ob,
|
|
ListBase *conlist,
|
|
std::set<Object *> &animated_objects)
|
|
{
|
|
bConstraint *con;
|
|
for (con = (bConstraint *)conlist->first; con; con = con->next) {
|
|
ListBase targets = {nullptr, nullptr};
|
|
|
|
const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
|
|
|
|
if (!bc_validateConstraints(con)) {
|
|
continue;
|
|
}
|
|
|
|
if (cti && cti->get_constraint_targets) {
|
|
bConstraintTarget *ct;
|
|
Object *obtar;
|
|
cti->get_constraint_targets(con, &targets);
|
|
for (ct = (bConstraintTarget *)targets.first; ct; ct = ct->next) {
|
|
obtar = ct->tar;
|
|
if (obtar) {
|
|
if (animated_objects.find(obtar) != animated_objects.end()) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void BCAnimationSampler::find_depending_animated(std::set<Object *> &animated_objects,
|
|
std::set<Object *> &candidates)
|
|
{
|
|
bool found_more;
|
|
do {
|
|
found_more = false;
|
|
std::set<Object *>::iterator it;
|
|
for (it = candidates.begin(); it != candidates.end(); ++it) {
|
|
Object *cob = *it;
|
|
ListBase *conlist = ED_object_constraint_active_list(cob);
|
|
if (is_animated_by_constraint(cob, conlist, animated_objects)) {
|
|
animated_objects.insert(cob);
|
|
candidates.erase(cob);
|
|
found_more = true;
|
|
break;
|
|
}
|
|
}
|
|
} while (found_more && !candidates.empty());
|
|
}
|
|
|
|
void BCAnimationSampler::get_animated_from_export_set(std::set<Object *> &animated_objects,
|
|
LinkNode &export_set)
|
|
{
|
|
/* Check if this object is animated. That is: Check if it has its own action, or:
|
|
*
|
|
* - Check if it has constraints to other objects.
|
|
* - at least one of the other objects is animated as well.
|
|
*/
|
|
|
|
animated_objects.clear();
|
|
std::set<Object *> static_objects;
|
|
std::set<Object *> candidates;
|
|
|
|
LinkNode *node;
|
|
for (node = &export_set; node; node = node->next) {
|
|
Object *cob = (Object *)node->link;
|
|
if (bc_has_animations(cob)) {
|
|
animated_objects.insert(cob);
|
|
}
|
|
else {
|
|
ListBase conlist = cob->constraints;
|
|
if (conlist.first) {
|
|
candidates.insert(cob);
|
|
}
|
|
}
|
|
}
|
|
find_depending_animated(animated_objects, candidates);
|
|
}
|
|
|
|
void BCAnimationSampler::get_object_frames(BCFrames &frames, Object *ob)
|
|
{
|
|
sample_data.get_frames(ob, frames);
|
|
}
|
|
|
|
void BCAnimationSampler::get_bone_frames(BCFrames &frames, Object *ob, Bone *bone)
|
|
{
|
|
sample_data.get_frames(ob, bone, frames);
|
|
}
|
|
|
|
bool BCAnimationSampler::get_bone_samples(BCMatrixSampleMap &samples, Object *ob, Bone *bone)
|
|
{
|
|
sample_data.get_matrices(ob, bone, samples);
|
|
return bc_is_animated(samples);
|
|
}
|
|
|
|
bool BCAnimationSampler::get_object_samples(BCMatrixSampleMap &samples, Object *ob)
|
|
{
|
|
sample_data.get_matrices(ob, samples);
|
|
return bc_is_animated(samples);
|
|
}
|
|
|
|
#if 0
|
|
/**
|
|
* Add sampled values to #FCurve
|
|
* If no #FCurve exists, create a temporary #FCurve;
|
|
* \note The temporary #FCurve will later be removed when the
|
|
* #BCAnimationSampler is removed (by its destructor).
|
|
*
|
|
* \param curve: The curve to which the data is added.
|
|
* \param matrices: The set of matrix values from where the data is taken.
|
|
* \param animation_type:
|
|
* - #BC_ANIMATION_EXPORT_SAMPLES: Use all matrix data.
|
|
* - #BC_ANIMATION_EXPORT_KEYS: Only take data from matrices for keyframes.
|
|
*/
|
|
void BCAnimationSampler::add_value_set(BCAnimationCurve &curve,
|
|
BCFrameSampleMap &samples,
|
|
BC_export_animation_type animation_type)
|
|
{
|
|
int array_index = curve.get_array_index();
|
|
const BC_animation_transform_type tm_type = curve.get_transform_type();
|
|
|
|
BCFrameSampleMap::iterator it;
|
|
for (it = samples.begin(); it != samples.end(); ++it) {
|
|
const int frame_index = nearbyint(it->first);
|
|
if (animation_type == BC_ANIMATION_EXPORT_SAMPLES || curve.is_keyframe(frame_index)) {
|
|
|
|
const BCSample *sample = it->second;
|
|
float val = 0;
|
|
|
|
int subindex = curve.get_subindex();
|
|
bool good;
|
|
if (subindex == -1) {
|
|
good = sample->get_value(tm_type, array_index, &val);
|
|
}
|
|
else {
|
|
good = sample->get_value(tm_type, array_index, &val, subindex);
|
|
}
|
|
|
|
if (good) {
|
|
curve.add_value(val, frame_index);
|
|
}
|
|
}
|
|
}
|
|
curve.remove_unused_keyframes();
|
|
curve.calchandles();
|
|
}
|
|
#endif
|
|
|
|
void BCAnimationSampler::generate_transform(Object *ob,
|
|
const BCCurveKey &key,
|
|
BCAnimationCurveMap &curves)
|
|
{
|
|
BCAnimationCurveMap::const_iterator it = curves.find(key);
|
|
if (it == curves.end()) {
|
|
curves[key] = new BCAnimationCurve(key, ob);
|
|
}
|
|
}
|
|
|
|
void BCAnimationSampler::generate_transforms(Object *ob,
|
|
const std::string prep,
|
|
const BC_animation_type type,
|
|
BCAnimationCurveMap &curves)
|
|
{
|
|
generate_transform(ob, BCCurveKey(type, prep + "location", 0), curves);
|
|
generate_transform(ob, BCCurveKey(type, prep + "location", 1), curves);
|
|
generate_transform(ob, BCCurveKey(type, prep + "location", 2), curves);
|
|
generate_transform(ob, BCCurveKey(type, prep + "rotation_euler", 0), curves);
|
|
generate_transform(ob, BCCurveKey(type, prep + "rotation_euler", 1), curves);
|
|
generate_transform(ob, BCCurveKey(type, prep + "rotation_euler", 2), curves);
|
|
generate_transform(ob, BCCurveKey(type, prep + "scale", 0), curves);
|
|
generate_transform(ob, BCCurveKey(type, prep + "scale", 1), curves);
|
|
generate_transform(ob, BCCurveKey(type, prep + "scale", 2), curves);
|
|
}
|
|
|
|
void BCAnimationSampler::generate_transforms(Object *ob, Bone *bone, BCAnimationCurveMap &curves)
|
|
{
|
|
std::string prep = "pose.bones[\"" + std::string(bone->name) + "\"].";
|
|
generate_transforms(ob, prep, BC_ANIMATION_TYPE_BONE, curves);
|
|
|
|
for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
|
|
generate_transforms(ob, child, curves);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Collect all keyframes from all animation curves related to the object.
|
|
* The bc_get... functions check for NULL and correct object type.
|
|
* The #add_keyframes_from() function checks for NULL.
|
|
*/
|
|
void BCAnimationSampler::initialize_keyframes(BCFrameSet &frameset, Object *ob)
|
|
{
|
|
frameset.clear();
|
|
add_keyframes_from(bc_getSceneObjectAction(ob), frameset);
|
|
add_keyframes_from(bc_getSceneCameraAction(ob), frameset);
|
|
add_keyframes_from(bc_getSceneLightAction(ob), frameset);
|
|
|
|
for (int a = 0; a < ob->totcol; a++) {
|
|
Material *ma = BKE_object_material_get(ob, a + 1);
|
|
add_keyframes_from(bc_getSceneMaterialAction(ma), frameset);
|
|
}
|
|
}
|
|
|
|
void BCAnimationSampler::initialize_curves(BCAnimationCurveMap &curves, Object *ob)
|
|
{
|
|
BC_animation_type object_type = BC_ANIMATION_TYPE_OBJECT;
|
|
|
|
bAction *action = bc_getSceneObjectAction(ob);
|
|
if (action) {
|
|
FCurve *fcu = (FCurve *)action->curves.first;
|
|
|
|
for (; fcu; fcu = fcu->next) {
|
|
object_type = BC_ANIMATION_TYPE_OBJECT;
|
|
if (ob->type == OB_ARMATURE) {
|
|
char *boneName = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones[");
|
|
if (boneName) {
|
|
object_type = BC_ANIMATION_TYPE_BONE;
|
|
MEM_freeN(boneName);
|
|
}
|
|
}
|
|
|
|
/* Adding action curves on object */
|
|
BCCurveKey key(object_type, fcu->rna_path, fcu->array_index);
|
|
curves[key] = new BCAnimationCurve(key, ob, fcu);
|
|
}
|
|
}
|
|
|
|
/* Add missing curves */
|
|
object_type = BC_ANIMATION_TYPE_OBJECT;
|
|
generate_transforms(ob, EMPTY_STRING, object_type, curves);
|
|
if (ob->type == OB_ARMATURE) {
|
|
bArmature *arm = (bArmature *)ob->data;
|
|
for (Bone *root_bone = (Bone *)arm->bonebase.first; root_bone; root_bone = root_bone->next) {
|
|
generate_transforms(ob, root_bone, curves);
|
|
}
|
|
}
|
|
|
|
/* Add curves on Object->data actions */
|
|
action = nullptr;
|
|
if (ob->type == OB_CAMERA) {
|
|
action = bc_getSceneCameraAction(ob);
|
|
object_type = BC_ANIMATION_TYPE_CAMERA;
|
|
}
|
|
else if (ob->type == OB_LAMP) {
|
|
action = bc_getSceneLightAction(ob);
|
|
object_type = BC_ANIMATION_TYPE_LIGHT;
|
|
}
|
|
|
|
if (action) {
|
|
/* Add light action or Camera action */
|
|
FCurve *fcu = (FCurve *)action->curves.first;
|
|
for (; fcu; fcu = fcu->next) {
|
|
BCCurveKey key(object_type, fcu->rna_path, fcu->array_index);
|
|
curves[key] = new BCAnimationCurve(key, ob, fcu);
|
|
}
|
|
}
|
|
|
|
/* Add curves on Object->material actions*/
|
|
object_type = BC_ANIMATION_TYPE_MATERIAL;
|
|
for (int a = 0; a < ob->totcol; a++) {
|
|
/* Export Material parameter animations. */
|
|
Material *ma = BKE_object_material_get(ob, a + 1);
|
|
if (ma) {
|
|
action = bc_getSceneMaterialAction(ma);
|
|
if (action) {
|
|
/* isMatAnim = true; */
|
|
FCurve *fcu = (FCurve *)action->curves.first;
|
|
for (; fcu; fcu = fcu->next) {
|
|
BCCurveKey key(object_type, fcu->rna_path, fcu->array_index, a);
|
|
curves[key] = new BCAnimationCurve(key, ob, fcu);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* ==================================================================== */
|
|
|
|
BCSample &BCSampleFrame::add(Object *ob)
|
|
{
|
|
BCSample *sample = new BCSample(ob);
|
|
sampleMap[ob] = sample;
|
|
return *sample;
|
|
}
|
|
|
|
/* Get the matrix for the given key, returns Unity when the key does not exist */
|
|
const BCSample *BCSampleFrame::get_sample(Object *ob) const
|
|
{
|
|
BCSampleMap::const_iterator it = sampleMap.find(ob);
|
|
if (it == sampleMap.end()) {
|
|
return nullptr;
|
|
}
|
|
return it->second;
|
|
}
|
|
|
|
const BCMatrix *BCSampleFrame::get_sample_matrix(Object *ob) const
|
|
{
|
|
BCSampleMap::const_iterator it = sampleMap.find(ob);
|
|
if (it == sampleMap.end()) {
|
|
return nullptr;
|
|
}
|
|
BCSample *sample = it->second;
|
|
return &sample->get_matrix();
|
|
}
|
|
|
|
/* Get the matrix for the given Bone, returns Unity when the Objewct is not sampled */
|
|
const BCMatrix *BCSampleFrame::get_sample_matrix(Object *ob, Bone *bone) const
|
|
{
|
|
BCSampleMap::const_iterator it = sampleMap.find(ob);
|
|
if (it == sampleMap.end()) {
|
|
return nullptr;
|
|
}
|
|
|
|
BCSample *sample = it->second;
|
|
const BCMatrix *bc_bone = sample->get_matrix(bone);
|
|
return bc_bone;
|
|
}
|
|
|
|
/* Check if the key is in this BCSampleFrame */
|
|
bool BCSampleFrame::has_sample_for(Object *ob) const
|
|
{
|
|
return sampleMap.find(ob) != sampleMap.end();
|
|
}
|
|
|
|
/* Check if the Bone is in this BCSampleFrame */
|
|
bool BCSampleFrame::has_sample_for(Object *ob, Bone *bone) const
|
|
{
|
|
const BCMatrix *bc_bone = get_sample_matrix(ob, bone);
|
|
return bc_bone;
|
|
}
|
|
|
|
/* ==================================================================== */
|
|
|
|
BCSample &BCSampleFrameContainer::add(Object *ob, int frame_index)
|
|
{
|
|
BCSampleFrame &frame = sample_frames[frame_index];
|
|
return frame.add(ob);
|
|
}
|
|
|
|
/* ====================================================== */
|
|
/* Below are the getters which we need to export the data */
|
|
/* ====================================================== */
|
|
|
|
/* Return either the BCSampleFrame or NULL if frame does not exist*/
|
|
BCSampleFrame *BCSampleFrameContainer::get_frame(int frame_index)
|
|
{
|
|
BCSampleFrameMap::iterator it = sample_frames.find(frame_index);
|
|
BCSampleFrame *frame = (it == sample_frames.end()) ? nullptr : &it->second;
|
|
return frame;
|
|
}
|
|
|
|
/* Return a list of all frames that need to be sampled */
|
|
int BCSampleFrameContainer::get_frames(std::vector<int> &frames) const
|
|
{
|
|
frames.clear(); /* safety; */
|
|
BCSampleFrameMap::const_iterator it;
|
|
for (it = sample_frames.begin(); it != sample_frames.end(); ++it) {
|
|
frames.push_back(it->first);
|
|
}
|
|
return frames.size();
|
|
}
|
|
|
|
int BCSampleFrameContainer::get_frames(Object *ob, BCFrames &frames) const
|
|
{
|
|
frames.clear(); /* safety; */
|
|
BCSampleFrameMap::const_iterator it;
|
|
for (it = sample_frames.begin(); it != sample_frames.end(); ++it) {
|
|
const BCSampleFrame &frame = it->second;
|
|
if (frame.has_sample_for(ob)) {
|
|
frames.push_back(it->first);
|
|
}
|
|
}
|
|
return frames.size();
|
|
}
|
|
|
|
int BCSampleFrameContainer::get_frames(Object *ob, Bone *bone, BCFrames &frames) const
|
|
{
|
|
frames.clear(); /* safety; */
|
|
BCSampleFrameMap::const_iterator it;
|
|
for (it = sample_frames.begin(); it != sample_frames.end(); ++it) {
|
|
const BCSampleFrame &frame = it->second;
|
|
if (frame.has_sample_for(ob, bone)) {
|
|
frames.push_back(it->first);
|
|
}
|
|
}
|
|
return frames.size();
|
|
}
|
|
|
|
int BCSampleFrameContainer::get_samples(Object *ob, BCFrameSampleMap &samples) const
|
|
{
|
|
samples.clear(); /* safety; */
|
|
BCSampleFrameMap::const_iterator it;
|
|
for (it = sample_frames.begin(); it != sample_frames.end(); ++it) {
|
|
const BCSampleFrame &frame = it->second;
|
|
const BCSample *sample = frame.get_sample(ob);
|
|
if (sample) {
|
|
samples[it->first] = sample;
|
|
}
|
|
}
|
|
return samples.size();
|
|
}
|
|
|
|
int BCSampleFrameContainer::get_matrices(Object *ob, BCMatrixSampleMap &samples) const
|
|
{
|
|
samples.clear(); /* safety; */
|
|
BCSampleFrameMap::const_iterator it;
|
|
for (it = sample_frames.begin(); it != sample_frames.end(); ++it) {
|
|
const BCSampleFrame &frame = it->second;
|
|
const BCMatrix *matrix = frame.get_sample_matrix(ob);
|
|
if (matrix) {
|
|
samples[it->first] = matrix;
|
|
}
|
|
}
|
|
return samples.size();
|
|
}
|
|
|
|
int BCSampleFrameContainer::get_matrices(Object *ob, Bone *bone, BCMatrixSampleMap &samples) const
|
|
{
|
|
samples.clear(); /* safety; */
|
|
BCSampleFrameMap::const_iterator it;
|
|
for (it = sample_frames.begin(); it != sample_frames.end(); ++it) {
|
|
const BCSampleFrame &frame = it->second;
|
|
const BCMatrix *sample = frame.get_sample_matrix(ob, bone);
|
|
if (sample) {
|
|
samples[it->first] = sample;
|
|
}
|
|
}
|
|
return samples.size();
|
|
}
|