blob: 233210a2a03742f346b9259a61d070e233477cd8 [file] [log] [blame]
#include "rive/bones/skin.hpp"
#include "rive/bones/bone.hpp"
#include "rive/bones/skinnable.hpp"
#include "rive/bones/tendon.hpp"
#include "rive/shapes/vertex.hpp"
#include "rive/shapes/path_vertex.hpp"
#include "rive/constraints/constraint.hpp"
using namespace rive;
Skin::~Skin() { delete[] m_BoneTransforms; }
StatusCode Skin::onAddedClean(CoreContext* context) {
m_WorldTransform[0] = xx();
m_WorldTransform[1] = xy();
m_WorldTransform[2] = yx();
m_WorldTransform[3] = yy();
m_WorldTransform[4] = tx();
m_WorldTransform[5] = ty();
m_Skinnable = Skinnable::from(parent());
if (m_Skinnable == nullptr) {
return StatusCode::MissingObject;
}
m_Skinnable->skin(this);
return StatusCode::Ok;
}
void Skin::update(ComponentDirt value) {
int bidx = 6;
for (auto tendon : m_Tendons) {
auto world = tendon->bone()->worldTransform() * tendon->inverseBind();
m_BoneTransforms[bidx++] = world[0];
m_BoneTransforms[bidx++] = world[1];
m_BoneTransforms[bidx++] = world[2];
m_BoneTransforms[bidx++] = world[3];
m_BoneTransforms[bidx++] = world[4];
m_BoneTransforms[bidx++] = world[5];
}
}
void Skin::buildDependencies() {
// depend on bones from tendons
for (auto tendon : m_Tendons) {
auto bone = tendon->bone();
bone->addDependent(this);
for (auto constraint : bone->peerConstraints()) {
constraint->parent()->addDependent(this);
}
}
// Make sure no-one is calling this twice.
assert(m_BoneTransforms == nullptr);
// We can now init the bone buffer.
auto size = (m_Tendons.size() + 1) * 6;
m_BoneTransforms = new float[size];
m_BoneTransforms[0] = 1;
m_BoneTransforms[1] = 0;
m_BoneTransforms[2] = 0;
m_BoneTransforms[3] = 1;
m_BoneTransforms[4] = 0;
m_BoneTransforms[5] = 0;
}
void Skin::deform(Span<Vertex*> vertices) {
for (auto vertex : vertices) {
vertex->deform(m_WorldTransform, m_BoneTransforms);
}
}
void Skin::addTendon(Tendon* tendon) { m_Tendons.push_back(tendon); }
void Skin::onDirty(ComponentDirt dirt) { m_Skinnable->markSkinDirty(); }