DragonBones / DragonBonesCPP

DragonBones C++ Runtime
MIT License
397 stars 228 forks source link

Procedural animations #176

Open rezydent opened 6 years ago

rezydent commented 6 years ago

Is there a proper way of programatically controlling animations at runtime for bones and constraints, that would also allow for blending with other, regular animations? So far I managed to do it for bones by modifying animation state timeline, but it's more of a hack, so I'm wondering if I'm doing this the hard way, or there really isn't any support for that.

akdcl commented 6 years ago

Hi, you can set bone.offset to modify bone's transform. https://github.com/DragonBones/DragonBonesCPP/blob/master/Cocos2DX_3.x/Demos/Classes/BoneOffset.h https://dragonbones.github.io/demo/BoneOffset/index.html https://dragonbones.github.io/demo/InverseKinematics/index.html

rezydent commented 6 years ago

Thanks! Unfortunately it doesn't mix with animation states, because it's just an additive transform, but I figured out a correction for this. Here is a quick draft in case someone will need it. I'm not sure if this covers blending by groups.

void dbSetPose(dragonBones::Bone *bone, dragonBones::Transform trf, std::string animation) {
    float weight = 1.0f;
    auto states = bone->getArmature()->getAnimation()->getStates();
    int baseLayer = bone->getArmature()->getAnimation()->getState(animation)->layer;
    bool beforeBaseAnimation = true; // Priority is layer first, and then order in state list

    for (auto state : states) {
        if (state->layer < baseLayer) {
            continue;
        }
        if (state->layer == baseLayer && beforeBaseAnimation) {
            continue;
        }

        if (state->getName().compare(animation) == 0) {
            weight = min(weight, state->_weightResult);
            beforeBaseAnimation = false;
        }
        else if (state->containsBoneMask(bone->getName())) {
            weight = min(weight, 1.0 - state->_weightResult); // Apply overlaid weights
        }
    }

    trf.x *= weight;
    trf.y *= weight;
    trf.rotation *= weight;
    bone->offset = trf;
    bone->invalidUpdate();
}