[SOLVED] - AnimControlCollection

Hello guys,
I have 3 different classes.
-Engine
-NodeBase
-Player

I defined a most of variables in Engine.h and use them at other classes via #include “Engine.h”
(like playerNP as NodePath or anim_control_collection as AnimControlCollection etc…)
Im trying to make playing animations. Here is my class functions;

//ENGINE CLASS
NodePath Engine::loadModel(string sNodeName, string sPath){
	NodePath NP = NodePath(sNodeName);
	NP = window->load_model(framework->get_models(), sPath);
	return NP;
}

NodePath Engine::loadModelRender(string sNodeName, string sPath) {
	NodePath NP = NodePath(sNodeName);
	NP = window->load_model(render, sPath);
	return NP;
}

NodePath Engine::loadModelToModel(NodePath sNode, string sPath)
{
	return window->load_model(sNode, sPath);
}
//NODEBASE CLASS
NodePath NodeBase::loadPlayerModel(const std::string modelName, LVecBase3 modelSize, LVecBase3 modelPos)
{
	const string _model_path = "bin/neuera/characters/models/" + modelName + ".bam";
	NodePath NP = Engine::loadModelRender("instance", _model_path);
	NP.set_name(modelName);
	NP.set_scale(modelSize);
	NP.set_pos(modelPos);
	return NP;
}

NodePath NodeBase::loadInstanceModel(const std::string modelName, LVecBase3 modelSize, LVecBase3 modelPos)
{
	const string _model_path = "bin/neuera/models/instances/" + modelName + ".bam";
	NodePath NP = Engine::loadModelRender("instance", _model_path);
	NP.set_name(modelName);
	NP.set_scale(modelSize);
	NP.set_pos(modelPos);
    return NP;
}

void NodeBase::loadAnimToInstance(NodePath _node, const std::string _anim)
{
	const string _actual_anim_name = _node.get_name() + "-" + _anim + ".bam";
	const string _anim_path = "bin/neuera/characters/anims/" + _actual_anim_name;
	Engine::loadModelToModel(_node, _anim_path);
	auto_bind(_node.node(), anim_control_collection);
	anim_control_collection.loop_all(true);
}

void NodeBase::setLoopMotion(NodePath _node, const std::string _anim)
{
	const string _actual_anim_name = _node.get_name() + "-" + _anim + ".bam";
	anim_control_collection.loop(_actual_anim_name, true);
}

void NodeBase::pushOnceMotion(NodePath _node, const std::string _anim)
{
	const string _actual_anim_name = _node.get_name() + "-" + _anim + ".bam";
	anim_control_collection.play(_actual_anim_name);
}
//PLAYER CLASS
Player::Player() {
	playerNP = NodeBase::loadPlayerModel("orc", { 5,5,5 }, { 135,182,0 });
	NodeBase::loadAnimToInstance(playerNP, "idle");
	NodeBase::loadAnimToInstance(playerNP, "run");
}
//Model: "orc.bam"
//Anims: "orc-idle.bam" and "orc-run.bam"

and i tried to test it with define_key;

void TestBindFunc(const Event* pTheEvent, void* pData) {
	NodeBase::setLoopMotion(playerNP, "idle"); //also tried pushOnceMotion
	std::cout << "Playing idle.." << std::endl;
}

void TestBindFunc2(const Event* pTheEvent, void* pData) {
	NodeBase::setLoopMotion(playerNP, "run");//also tried pushOnceMotion
	std::cout << "Playing run.." << std::endl;
}

//DEFINE_KEYS
framework->define_key("s-up", "Test Bind s", TestBindFunc, nullptr);
framework->define_key("w-up", "Test Bind w", TestBindFunc2, nullptr);

But it didn’t work. Im not sure if this usage is ok for AnimControlCollection?
What is the right way to use AnimControlCollection?
Thanks all…

You may not know, but the forum has a search function. I found this mention.

https://docs.panda3d.org/1.10/cpp/introduction/tutorial/loading-and-animating-the-panda-model

Actually i did the same thing but i couldn’t switch between run and idle animations that was my point but thanks :+1:

As @serega-kkz said i must search forum more :slight_smile:
also as @dri said;

Idk why but using temp collection solved the problem and here the final changes;

  • used temp AnimControlCollection
  • removed “.bam” extension string from animation names
void NodeBase::loadAnimToInstance(NodePath _node, const std::string _anim, int index)
{
	const string _actual_anim_name = _node.get_name() + "-" + _anim;
	const string _anim_path = "bin/neuera/characters/anims/" + _actual_anim_name + ".bam";
	NodePath animNP = Engine::loadModelToModel(_node, _anim_path);
	AnimControlCollection tmpCol;
	auto_bind(_node.node(), tmpCol);
	PT(AnimControl) animPtr = tmpCol.get_anim(0);
	anim_control_collection.store_anim(animPtr, _actual_anim_name);
	string animName = tmpCol.get_anim_name(0);
	std::cout << animName << std::endl;
	tmpCol.unbind_anim(animName);
	animNP.detach_node();
}

void NodeBase::setLoopMotion(NodePath _node, const std::string _anim)
{
	const string _actual_anim_name = _node.get_name() + "-" + _anim;
	anim_control_collection.loop(_actual_anim_name, true);
}

void NodeBase::pushOnceMotion(NodePath _node, const std::string _anim)
{
	const string _actual_anim_name = _node.get_name() + "-" + _anim;
	anim_control_collection.play(_actual_anim_name);
}

https://streamable.com/gdq1r6

1 Like

Also one more question;

	NodePath child = playerNP.find("**/+Character");
	Character* ch = DCAST(Character, child.node());
	std::cout << ch->get_num_bundles() << std::endl;
	PartBundle* bundle = ch->get_bundle(0);
	bundle->set_frame_blend_flag(true); //Working very well (i can see it with animPtr->set_play_rate(0.01); )
	bundle->set_anim_blend_flag(true); //But if i set this true animations not playing! why???

Those do two different things, I believe:

The “set_frame_blend_flag” method determines whether Panda will animate a character essentially as though there were frames between the actual frames, thus potentially giving smoother animation.

On the other hand, however, the “set_anim_blend_flag” method determines whether Panda will allow the developer to fade animations into each other–whether softly ending one and starting the next, or mixing two (or more) together for the duration of their run, or whatever.

And importantly, animation-blending requires, I believe, that you specify the weight for each animation that is to be played–the degree to which they contribute to the final, blended animation.

I gather that the default value for this weight is 0–thus causing the animation to contribute nothing to the final animation, and so to appear to not be playing.

To deal with this, use the “set_control_effect” method to specify the blending-weight for your animations.

For more information, see the following manual page:
https://docs.panda3d.org/1.10/python/programming/models-and-actors/actor-animations

(The above is in Python, but the C++ version doesn’t seem to have example code, and I’m not confident of its method-names.)

3 Likes

Thank you @Thaumaturge :heart:

Here my final code, im open to any improvements/corrections from you guys thanks!

1 Like

Congratulations and well done on getting it working! :slight_smile:

1 Like