2018-03-11 19:23:08 +01:00
|
|
|
/*
|
|
|
|
* ***** 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.
|
|
|
|
*
|
2018-03-23 10:18:12 +01:00
|
|
|
* The Original Code is Copyright (C) 2008 Blender Foundation.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s): Blender Foundation
|
2018-03-11 19:23:08 +01:00
|
|
|
*
|
|
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "BCAnimationCurve.h"
|
|
|
|
|
2018-03-22 23:20:02 +01:00
|
|
|
std::map<std::string, BC_animation_transform_type> BC_ANIMATION_TYPE_FROM_NAME = {
|
|
|
|
{ "rotation", BC_ANIMATION_TYPE_ROTATION },
|
|
|
|
{ "rotation_euler", BC_ANIMATION_TYPE_ROTATION_EULER },
|
|
|
|
{ "rotation_quaternion", BC_ANIMATION_TYPE_ROTATION_QUAT },
|
|
|
|
{ "scale", BC_ANIMATION_TYPE_SCALE },
|
|
|
|
{ "location", BC_ANIMATION_TYPE_LOCATION },
|
|
|
|
|
|
|
|
/* Materials */
|
|
|
|
{ "specular_hardness", BC_ANIMATION_TYPE_SPECULAR_HARDNESS },
|
|
|
|
{ "specular_color", BC_ANIMATION_TYPE_SPECULAR_COLOR },
|
|
|
|
{ "diffuse_color", BC_ANIMATION_TYPE_DIFFUSE_COLOR },
|
|
|
|
{ "alpha", BC_ANIMATION_TYPE_ALPHA },
|
|
|
|
{ "ior", BC_ANIMATION_TYPE_IOR },
|
|
|
|
|
|
|
|
/* Lamps */
|
2018-03-24 16:57:46 +01:00
|
|
|
{ "color", BC_ANIMATION_TYPE_LIGHT_COLOR },
|
2018-03-22 23:20:02 +01:00
|
|
|
{ "fall_off_angle", BC_ANIMATION_TYPE_FALL_OFF_ANGLE },
|
|
|
|
{ "fall_off_exponent", BC_ANIMATION_TYPE_FALL_OFF_EXPONENT },
|
|
|
|
{ "blender/blender_dist", BC_ANIMATION_TYPE_BLENDER_DIST },
|
|
|
|
/* Lamp RNA to animation type */
|
|
|
|
{ "spot_size", BC_ANIMATION_TYPE_FALL_OFF_ANGLE },
|
|
|
|
{ "spot_blend", BC_ANIMATION_TYPE_FALL_OFF_EXPONENT },
|
|
|
|
{ "distance", BC_ANIMATION_TYPE_BLENDER_DIST },
|
|
|
|
|
|
|
|
/* Cameras */
|
|
|
|
{ "xfov", BC_ANIMATION_TYPE_XFOV },
|
|
|
|
{ "xmag", BC_ANIMATION_TYPE_XMAG },
|
|
|
|
{ "zfar", BC_ANIMATION_TYPE_ZFAR },
|
|
|
|
{ "znear", BC_ANIMATION_TYPE_ZNEAR },
|
|
|
|
/* Camera RNA to animation type */
|
|
|
|
{ "lens", BC_ANIMATION_TYPE_XFOV },
|
|
|
|
{ "ortho_scale", BC_ANIMATION_TYPE_XMAG },
|
|
|
|
{ "clip_end", BC_ANIMATION_TYPE_ZFAR },
|
|
|
|
{ "clip_start", BC_ANIMATION_TYPE_ZNEAR }
|
|
|
|
|
|
|
|
};
|
|
|
|
|
2018-03-11 19:23:08 +01:00
|
|
|
void BCAnimationCurve::delete_fcurve(FCurve *fcu)
|
|
|
|
{
|
|
|
|
free_fcurve(fcu);
|
|
|
|
}
|
|
|
|
|
|
|
|
FCurve *BCAnimationCurve::create_fcurve(int array_index, const char *rna_path)
|
|
|
|
{
|
|
|
|
FCurve *fcu = (FCurve *)MEM_callocN(sizeof(FCurve), "FCurve");
|
|
|
|
fcu->flag = (FCURVE_VISIBLE | FCURVE_AUTO_HANDLES | FCURVE_SELECTED);
|
|
|
|
fcu->rna_path = BLI_strdupn(rna_path, strlen(rna_path));
|
|
|
|
fcu->array_index = array_index;
|
|
|
|
return fcu;
|
|
|
|
}
|
|
|
|
|
|
|
|
void BCAnimationCurve::create_bezt(float frame, float output)
|
|
|
|
{
|
|
|
|
FCurve *fcu = get_edit_fcurve();
|
|
|
|
BezTriple bez;
|
|
|
|
memset(&bez, 0, sizeof(BezTriple));
|
|
|
|
bez.vec[1][0] = frame;
|
|
|
|
bez.vec[1][1] = output;
|
|
|
|
bez.ipo = U.ipo_new; /* use default interpolation mode here... */
|
|
|
|
bez.f1 = bez.f2 = bez.f3 = SELECT;
|
|
|
|
bez.h1 = bez.h2 = HD_AUTO;
|
2018-03-17 13:45:32 +01:00
|
|
|
insert_bezt_fcurve(fcu, &bez, INSERTKEY_NOFLAGS);
|
2018-03-11 19:23:08 +01:00
|
|
|
calchandles_fcurve(fcu);
|
|
|
|
}
|
|
|
|
|
2018-03-17 13:40:46 +01:00
|
|
|
BCAnimationCurve::BCAnimationCurve()
|
2018-03-11 19:23:08 +01:00
|
|
|
{
|
2018-03-17 13:40:46 +01:00
|
|
|
this->fcurve = nullptr;
|
|
|
|
this->type = BC_ANIMATION_CURVE_TYPE_UNKNOWN;
|
2018-03-22 23:20:02 +01:00
|
|
|
this->curve_is_local_copy = false;
|
2018-03-17 13:40:46 +01:00
|
|
|
}
|
|
|
|
|
2018-03-22 23:20:02 +01:00
|
|
|
BCAnimationCurve::BCAnimationCurve(const BC_animation_curve_type type, FCurve *fcu)
|
|
|
|
{
|
|
|
|
init(type, fcu);
|
|
|
|
}
|
|
|
|
|
|
|
|
void BCAnimationCurve::init(const BC_animation_curve_type type, const std::string path, const int index)
|
2018-03-17 13:40:46 +01:00
|
|
|
{
|
|
|
|
this->curve_key.init(path, index);
|
|
|
|
this->fcurve = nullptr; // create_fcurve(index, path.c_str());
|
|
|
|
this->type = type;
|
2018-03-22 23:20:02 +01:00
|
|
|
this->curve_is_local_copy = false;
|
2018-03-17 13:40:46 +01:00
|
|
|
}
|
|
|
|
|
2018-03-24 16:57:46 +01:00
|
|
|
void BCAnimationCurve::init(const BC_animation_curve_type type, FCurve *fcu, int tag)
|
2018-03-17 13:40:46 +01:00
|
|
|
{
|
|
|
|
this->curve_key.init(std::string(fcu->rna_path), fcu->array_index);
|
2018-03-11 19:23:08 +01:00
|
|
|
this->fcurve = fcu;
|
|
|
|
this->type = type;
|
2018-03-22 23:20:02 +01:00
|
|
|
this->curve_is_local_copy = false; // make sure the curve is destroyed later;
|
2018-03-24 16:57:46 +01:00
|
|
|
this->tag = tag;
|
2018-03-11 19:23:08 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
BCAnimationCurve::~BCAnimationCurve()
|
|
|
|
{
|
|
|
|
if (curve_is_local_copy && fcurve) {
|
2018-03-17 13:40:46 +01:00
|
|
|
//fprintf(stderr, "removed fcurve %s\n", fcurve->rna_path);
|
2018-03-11 19:23:08 +01:00
|
|
|
delete_fcurve(fcurve);
|
2018-03-17 13:40:46 +01:00
|
|
|
this->fcurve = nullptr;
|
2018-03-11 19:23:08 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const BC_animation_curve_type BCAnimationCurve::get_channel_type() const
|
|
|
|
{
|
|
|
|
return type;
|
|
|
|
}
|
|
|
|
|
2018-03-22 23:20:02 +01:00
|
|
|
const BC_animation_transform_type BCAnimationCurve::get_transform_type() const
|
|
|
|
{
|
|
|
|
BC_animation_transform_type tm_type;
|
|
|
|
std::string target = get_channel_target();
|
|
|
|
std::map<std::string, BC_animation_transform_type>::iterator it = BC_ANIMATION_TYPE_FROM_NAME.find(target);
|
|
|
|
tm_type = (it != BC_ANIMATION_TYPE_FROM_NAME.end()) ? it->second : BC_ANIMATION_TYPE_UNKNOWN;
|
|
|
|
return tm_type;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-03-11 19:23:08 +01:00
|
|
|
const std::string BCAnimationCurve::get_channel_target() const
|
|
|
|
{
|
2018-03-17 13:40:46 +01:00
|
|
|
const std::string path = curve_key.path();
|
|
|
|
return bc_string_after(path, '.');
|
2018-03-11 19:23:08 +01:00
|
|
|
}
|
|
|
|
|
2018-03-17 13:40:46 +01:00
|
|
|
const std::string BCAnimationCurve::get_animation_name(Object *ob) const
|
2018-03-11 19:23:08 +01:00
|
|
|
{
|
|
|
|
std::string name;
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case BC_ANIMATION_CURVE_TYPE_OBJECT:
|
|
|
|
name = id_name(ob);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case BC_ANIMATION_CURVE_TYPE_BONE:
|
|
|
|
if (fcurve == NULL || fcurve->rna_path == NULL)
|
|
|
|
name = "";
|
|
|
|
else {
|
2018-03-22 23:20:02 +01:00
|
|
|
const char *boneName = BLI_str_quoted_substrN(fcurve->rna_path, "pose.bones[");
|
2018-03-11 19:23:08 +01:00
|
|
|
name = (boneName) ? std::string(boneName) : "";
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case BC_ANIMATION_CURVE_TYPE_CAMERA:
|
|
|
|
name = id_name(ob) + "-camera";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case BC_ANIMATION_CURVE_TYPE_LIGHT:
|
|
|
|
name = id_name(ob) + "-light";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case BC_ANIMATION_CURVE_TYPE_MATERIAL:
|
|
|
|
name = id_name(ob) + "-material";
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
name = "";
|
|
|
|
}
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
|
|
|
const int BCAnimationCurve::get_array_index() const
|
|
|
|
{
|
2018-03-17 13:40:46 +01:00
|
|
|
return curve_key.index();
|
|
|
|
}
|
|
|
|
|
|
|
|
const std::string BCAnimationCurve::get_rna_path() const
|
|
|
|
{
|
|
|
|
return curve_key.path();
|
2018-03-11 19:23:08 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
const int BCAnimationCurve::size() const
|
|
|
|
{
|
2018-03-22 23:20:02 +01:00
|
|
|
return samples.size();
|
2018-03-11 19:23:08 +01:00
|
|
|
}
|
|
|
|
|
2018-03-22 23:20:02 +01:00
|
|
|
const int BCAnimationCurve::closest_index_above(const float sample_frame, const int start_at) const
|
2018-03-11 19:23:08 +01:00
|
|
|
{
|
|
|
|
if (fcurve == NULL)
|
|
|
|
return -1;
|
|
|
|
|
2018-03-22 23:20:02 +01:00
|
|
|
const int cframe = fcurve->bezt[start_at].vec[1][0]; // inacurate!
|
2018-03-11 19:23:08 +01:00
|
|
|
|
|
|
|
if (fabs(cframe - sample_frame) < 0.00001)
|
|
|
|
return start_at;
|
|
|
|
return (fcurve->totvert > start_at + 1) ? start_at + 1 : start_at;
|
|
|
|
}
|
|
|
|
|
2018-03-22 23:20:02 +01:00
|
|
|
const int BCAnimationCurve::closest_index_below(const float sample_frame) const
|
2018-03-11 19:23:08 +01:00
|
|
|
{
|
2018-03-22 23:20:02 +01:00
|
|
|
if (fcurve == nullptr)
|
2018-03-11 19:23:08 +01:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
float lower_frame = sample_frame;
|
|
|
|
float upper_frame = sample_frame;
|
|
|
|
int lower_index = 0;
|
|
|
|
int upper_index = 0;
|
|
|
|
|
|
|
|
for (int fcu_index = 0; fcu_index < fcurve->totvert; ++fcu_index) {
|
|
|
|
upper_index = fcu_index;
|
|
|
|
|
2018-03-22 23:20:02 +01:00
|
|
|
const int cframe = fcurve->bezt[fcu_index].vec[1][0]; // inacurate!
|
2018-03-11 19:23:08 +01:00
|
|
|
if (cframe <= sample_frame) {
|
|
|
|
lower_frame = cframe;
|
|
|
|
lower_index = fcu_index;
|
|
|
|
}
|
|
|
|
if (cframe >= sample_frame) {
|
|
|
|
upper_frame = cframe;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lower_index == upper_index)
|
|
|
|
return lower_index;
|
|
|
|
|
2018-03-22 23:20:02 +01:00
|
|
|
const float fraction = float(sample_frame - lower_frame) / (upper_frame - lower_frame);
|
2018-03-11 19:23:08 +01:00
|
|
|
return (fraction < 0.5) ? lower_index : upper_index;
|
|
|
|
}
|
|
|
|
|
|
|
|
const int BCAnimationCurve::get_ipo(float sample_frame) const
|
|
|
|
{
|
2018-03-22 23:20:02 +01:00
|
|
|
const int index = closest_index_below(sample_frame);
|
2018-03-11 19:23:08 +01:00
|
|
|
if (index < 0)
|
|
|
|
return BEZT_IPO_BEZ;
|
|
|
|
return fcurve->bezt[index].ipo;
|
|
|
|
}
|
|
|
|
|
|
|
|
const FCurve *BCAnimationCurve::get_fcurve() const
|
|
|
|
{
|
|
|
|
return fcurve;
|
|
|
|
}
|
|
|
|
|
|
|
|
FCurve *BCAnimationCurve::get_edit_fcurve()
|
|
|
|
{
|
|
|
|
if (!curve_is_local_copy) {
|
|
|
|
|
2018-03-17 13:40:46 +01:00
|
|
|
if (fcurve) {
|
|
|
|
fcurve = copy_fcurve(fcurve);
|
|
|
|
//fprintf(stderr, "Copy to temporary fcurve %s (for editing)\n", fcurve->rna_path);
|
|
|
|
}
|
|
|
|
else {
|
2018-03-22 23:20:02 +01:00
|
|
|
const int index = curve_key.index();
|
2018-03-17 13:40:46 +01:00
|
|
|
const std::string &path = curve_key.path();
|
|
|
|
fcurve = create_fcurve(index, path.c_str());
|
|
|
|
//fprintf(stderr, "Create temporary fcurve %s (for editing)\n", fcurve->rna_path);
|
|
|
|
}
|
2018-03-11 19:23:08 +01:00
|
|
|
|
|
|
|
/* Replacing the pointer here is OK because the original value
|
|
|
|
of FCurve was a const pointer into Blender territory. We do not
|
|
|
|
touch that! We use the local copy to prepare for export.
|
|
|
|
*/
|
|
|
|
curve_is_local_copy = true;
|
|
|
|
}
|
|
|
|
return fcurve;
|
|
|
|
}
|
|
|
|
|
2018-03-17 13:40:46 +01:00
|
|
|
Bone *BCAnimationCurve::get_bone(Object *ob) const
|
2018-03-11 19:23:08 +01:00
|
|
|
{
|
2018-03-17 13:40:46 +01:00
|
|
|
if (ob->type != OB_ARMATURE ||
|
|
|
|
type != BC_ANIMATION_CURVE_TYPE_BONE ||
|
|
|
|
!fcurve ||
|
|
|
|
!fcurve->rna_path)
|
|
|
|
return nullptr;
|
|
|
|
|
2018-03-22 23:20:02 +01:00
|
|
|
const char *boneName = BLI_str_quoted_substrN(fcurve->rna_path, "pose.bones[");
|
2018-03-17 13:40:46 +01:00
|
|
|
|
|
|
|
if (!boneName)
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
Bone *bone = BKE_armature_find_bone_name((bArmature *)ob->data, boneName);
|
|
|
|
return bone;
|
|
|
|
|
2018-03-11 19:23:08 +01:00
|
|
|
}
|
|
|
|
|
2018-03-22 23:20:02 +01:00
|
|
|
void BCAnimationCurve::calchandles()
|
|
|
|
{
|
|
|
|
FCurve *fcu = this->get_edit_fcurve();
|
|
|
|
if(fcu)
|
|
|
|
calchandles_fcurve(fcu);
|
|
|
|
}
|
|
|
|
|
|
|
|
void BCAnimationCurve::remove_unused_keyframes()
|
2018-03-11 19:23:08 +01:00
|
|
|
{
|
|
|
|
FCurve *fcu = get_edit_fcurve();
|
2018-03-22 23:20:02 +01:00
|
|
|
if (fcu) {
|
|
|
|
BezTriple *bezt = fcu->bezt;
|
|
|
|
for (int i = 0; i < fcu->totvert; bezt++, i++) {
|
|
|
|
const int frame_index = bezt->vec[1][0];
|
|
|
|
BCValueMap::const_iterator it = samples.find(frame_index);
|
|
|
|
if (it == samples.end()) {
|
|
|
|
fcu->bezt[i].f2 |= SELECT;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
fcu->bezt[i].f2 &= ~SELECT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
delete_fcurve_keys(fcu);
|
|
|
|
}
|
|
|
|
}
|
2018-03-17 13:40:46 +01:00
|
|
|
|
2018-03-22 23:20:02 +01:00
|
|
|
void BCAnimationCurve::add_value(const float val, const int frame_index)
|
|
|
|
{
|
|
|
|
FCurve *fcu = get_edit_fcurve();
|
|
|
|
if (fcu) {
|
|
|
|
const float eval = evaluate_fcurve(fcu, frame_index);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This is a bit tricky here. We actually only insert a keyframe into the FCurve
|
|
|
|
* Preserving the current value. Then we add the frame index and the "true" value
|
|
|
|
* into a separate value_map <frame, value>
|
|
|
|
*
|
|
|
|
* Reason: we need the Fcurve handles later when we want to export the values as a Bezier curve
|
|
|
|
* XXX: This is actually not correct. But sometimes it works nicely. this needs more
|
|
|
|
* experimenting
|
|
|
|
*/
|
|
|
|
|
|
|
|
insert_vert_fcurve(fcu, frame_index, eval, (eBezTriple_KeyframeType)BEZT_IPO_BEZ, INSERTKEY_NO_USERPREF);
|
|
|
|
samples[frame_index] = val;
|
|
|
|
|
|
|
|
if (samples.size() == 1)
|
|
|
|
min = max = val;
|
|
|
|
else {
|
|
|
|
if (val < min)
|
|
|
|
min = val;
|
|
|
|
if (val > max)
|
|
|
|
max = val;
|
|
|
|
}
|
|
|
|
}
|
2018-03-11 19:23:08 +01:00
|
|
|
}
|
|
|
|
|
2018-03-23 15:49:06 +01:00
|
|
|
|
2018-03-11 19:23:08 +01:00
|
|
|
/*
|
2018-03-24 16:57:46 +01:00
|
|
|
Pick the value from the sample according to the definition of the FCurve
|
2018-03-11 19:23:08 +01:00
|
|
|
*/
|
2018-03-23 15:49:06 +01:00
|
|
|
bool BCAnimationCurve::add_value(const BCSample &sample, int frame)
|
2018-03-11 19:23:08 +01:00
|
|
|
{
|
2018-03-24 16:57:46 +01:00
|
|
|
const BC_animation_transform_type tm_type = get_transform_type();
|
2018-03-17 13:40:46 +01:00
|
|
|
const int array_index = curve_key.index();
|
2018-03-23 15:49:06 +01:00
|
|
|
float val = 0;
|
2018-03-11 19:23:08 +01:00
|
|
|
|
2018-03-24 16:57:46 +01:00
|
|
|
bool good = sample.get_value(tm_type, array_index, &val);
|
2018-03-23 15:49:06 +01:00
|
|
|
if (good) {
|
|
|
|
add_value(val, frame);
|
2018-03-11 19:23:08 +01:00
|
|
|
}
|
2018-03-23 15:49:06 +01:00
|
|
|
return good;
|
2018-03-11 19:23:08 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Return the frames of the sampled curve;
|
|
|
|
Note: If the curve was not sampled, the
|
|
|
|
returned vector is empty
|
|
|
|
*/
|
2018-03-23 09:50:18 +01:00
|
|
|
|
|
|
|
void BCAnimationCurve::get_key_frames(BCFrames &frames) const
|
2018-03-11 19:23:08 +01:00
|
|
|
{
|
2018-03-23 09:50:18 +01:00
|
|
|
if (fcurve) {
|
|
|
|
for (int i = 0; i < fcurve->totvert; i++) {
|
|
|
|
const float val = fcurve->bezt[i].vec[1][0];
|
|
|
|
frames.push_back(val);
|
|
|
|
}
|
2018-03-11 19:23:08 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-23 09:50:18 +01:00
|
|
|
void BCAnimationCurve::get_sampled_frames(BCFrames &frames, bool fallback) const
|
|
|
|
{
|
|
|
|
frames.clear();
|
|
|
|
if (samples.size() == 0 && fallback) {
|
|
|
|
return get_key_frames(frames);
|
|
|
|
}
|
|
|
|
else if (samples.size() > 0) {
|
|
|
|
BCValueMap::const_iterator it;
|
|
|
|
for (it = samples.begin(); it != samples.end(); ++it) {
|
|
|
|
//float val = evaluate_fcurve(fcurve, *it);
|
|
|
|
const int val = it->first;
|
|
|
|
frames.push_back(val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void BCAnimationCurve::get_sampled_frames(BCFrameSet &frames) const
|
2018-03-11 19:23:08 +01:00
|
|
|
{
|
2018-03-22 23:20:02 +01:00
|
|
|
BCValueMap::const_iterator it;
|
|
|
|
for (it = samples.begin(); it != samples.end(); ++it) {
|
|
|
|
const float val = it->first;
|
|
|
|
frames.insert(val);
|
2018-03-17 13:40:46 +01:00
|
|
|
}
|
2018-03-11 19:23:08 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Return the ctimes of the sampled curve;
|
|
|
|
Note: If the curve was not sampled, the
|
|
|
|
returned vector is empty
|
|
|
|
*/
|
2018-03-22 23:20:02 +01:00
|
|
|
void BCAnimationCurve::get_times(BCTimes ×, Scene *scene) const
|
2018-03-11 19:23:08 +01:00
|
|
|
{
|
2018-03-22 23:20:02 +01:00
|
|
|
BCValueMap::const_iterator it;
|
|
|
|
for (it = samples.begin(); it != samples.end(); ++it) {
|
|
|
|
const float time = FRA2TIME(it->first); // implicit use of scene
|
|
|
|
times.push_back(time);
|
2018-03-17 13:40:46 +01:00
|
|
|
}
|
2018-03-11 19:23:08 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Return the ctimes of the sampled curve;
|
|
|
|
Note: If the curve was not sampled, the
|
|
|
|
returned vector is empty
|
|
|
|
*/
|
2018-03-23 09:50:18 +01:00
|
|
|
void BCAnimationCurve::get_key_values(BCValues &values) const
|
2018-03-11 19:23:08 +01:00
|
|
|
{
|
2018-03-23 09:50:18 +01:00
|
|
|
if (fcurve) {
|
|
|
|
for (int i = 0; i < fcurve->totvert; i++) {
|
|
|
|
const float val = fcurve->bezt[i].vec[1][1];
|
|
|
|
values.push_back(val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void BCAnimationCurve::get_sampled_values(BCValues &values, bool fallback) const
|
|
|
|
{
|
|
|
|
values.clear();
|
|
|
|
if (samples.size() == 0 && fallback) {
|
|
|
|
return get_key_values(values);
|
|
|
|
}
|
|
|
|
else if (samples.size() > 0) {
|
|
|
|
BCValueMap::const_iterator it;
|
2018-03-22 23:20:02 +01:00
|
|
|
for (it = samples.begin(); it != samples.end(); ++it) {
|
|
|
|
//float val = evaluate_fcurve(fcurve, *it);
|
|
|
|
const float val = it->second;
|
2018-03-17 13:40:46 +01:00
|
|
|
values.push_back(val);
|
|
|
|
}
|
2018-03-23 09:50:18 +01:00
|
|
|
}
|
2018-03-17 13:40:46 +01:00
|
|
|
}
|
|
|
|
|
2018-03-23 09:50:18 +01:00
|
|
|
|
2018-03-22 23:20:02 +01:00
|
|
|
bool BCAnimationCurve::is_flat()
|
|
|
|
{
|
|
|
|
static float MIN_DISTANCE = 0.00001;
|
|
|
|
return fabs(max - min) < MIN_DISTANCE;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool BCAnimationCurve::is_flat_line(BCValues &values)
|
2018-03-17 13:40:46 +01:00
|
|
|
{
|
|
|
|
static float MIN_DISTANCE = 0.00001;
|
|
|
|
|
|
|
|
if (values.size() < 2)
|
|
|
|
return true; // need at least 2 entries to be not flat
|
|
|
|
|
2018-03-22 23:20:02 +01:00
|
|
|
const float ref = values[0];
|
2018-03-17 13:40:46 +01:00
|
|
|
for (int index = 1; index < values.size(); index++) {
|
2018-03-22 23:20:02 +01:00
|
|
|
const float val = values[index];
|
2018-03-17 13:40:46 +01:00
|
|
|
if (fabs(val - ref) > MIN_DISTANCE) {
|
|
|
|
return false;
|
|
|
|
}
|
2018-03-11 19:23:08 +01:00
|
|
|
}
|
2018-03-17 13:40:46 +01:00
|
|
|
return true;
|
2018-03-11 19:23:08 +01:00
|
|
|
}
|
|
|
|
|
2018-03-22 23:20:02 +01:00
|
|
|
bool BCAnimationCurve::is_rot() const
|
|
|
|
{
|
|
|
|
return bc_startswith(get_channel_target(), "rotation");
|
|
|
|
}
|
|
|
|
|
2018-03-24 16:57:46 +01:00
|
|
|
const int BCAnimationCurve::get_tag() const
|
|
|
|
{
|
|
|
|
return tag;
|
|
|
|
}
|
|
|
|
|
2018-03-22 23:20:02 +01:00
|
|
|
bool BCAnimationCurve::is_keyframe(int frame) {
|
|
|
|
if (this->fcurve == nullptr)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
for (int i = 0; i < fcurve->totvert; ++i) {
|
|
|
|
const int cframe = fcurve->bezt[i].vec[1][0];
|
|
|
|
if (cframe == frame)
|
|
|
|
return true;
|
|
|
|
if (cframe > frame)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2018-03-11 19:23:08 +01:00
|
|
|
|
|
|
|
/* Needed for adding a BCAnimationCurve into a BCAnimationCurveSet */
|
|
|
|
inline bool operator< (const BCAnimationCurve& lhs, const BCAnimationCurve& rhs) {
|
|
|
|
std::string lhtgt = lhs.get_channel_target();
|
|
|
|
std::string rhtgt = rhs.get_channel_target();
|
|
|
|
if (lhtgt == rhtgt)
|
|
|
|
{
|
2018-03-22 23:20:02 +01:00
|
|
|
const int lha = lhs.get_array_index();
|
|
|
|
const int rha = rhs.get_array_index();
|
2018-03-11 19:23:08 +01:00
|
|
|
return lha < rha;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return lhtgt < rhtgt;
|
|
|
|
}
|