[SOLVED] Setting animation play rate

Hi!

I am using C++ for working with Panda3d and need to increase and decrease the playing rate of animation depending on input by the HMD device.
I noticed python wrapper for models with animations (Actor) is huge. I don’t have enough time on my hands to reverse it and come out with a C++ function. It would be great if someone helped me with this - i.e. how to set an animation’s play rate depending on a variable that constantly changes with time, in C++.

I have two egg files, one holding the model and other, animation.

Why can’t you use the provided way? Can’t you pass your variable to set_play_rate?

The provided way that you have mentioned is for Python and has been implemented in Actor class, which is a wrapper for controlling models with animation.

The set_play_rate function that you have mentioned is from AnimInterface specification. As I recall, interfaces have only declarations and no definitions. To use this method, I’d have to use a class that implements it, which I am unable to find :frowning:
AnimControl’s source file does not contain the implementation of this methd :frowning:

AnimControl inherits from AnimInterface, and thus also inherits set_play_rate().

David

I guess I mixed up my C# and C++ background. Sorry!

I refered some other post by you and wrote the follwoing lines

NodePath child = this->jester.find("**/+Character");
			
assert(!child.is_empty());
Character *ch = DCAST(Character, child.node());
assert(ch != NULL);
			
PartBundle *bundle = ch->get_bundle(0);
assert(bundle != NULL); 
animControl = new AnimControl(animationName, bundle, 30, 60);

AnimControl *animControl is member of a class that holds the path of the animation in form “…/…/models/anim.egg”.

When I do animControl->play() or animControl->set_play_rate(0.1), nothing’s happening. I think this is because I have not associated any model to animControl. Can this be the reason for nothing happening? If yes, then how do I associate the model to the animControl object? What else can be wrong?

Looks like the object is already associated via the PartBundle. So what can be the problem now?

You can’t create an AnimControl directly; its constructor is only public because other systems within Panda need to construct an AnimControl.

An AnimControl is normally created as the result of binding a Character to its animation. A correctly-constructed AnimControl returned by PartBundle::bind_anim().

You can call bind_anim() directly, but the easiest way to create an AnimControl in C++ code is to use the auto_bind() function; there is an illustration of this in the pview.cxx source code, and probably in several forum posts.

Edit: also note that, as a reference-counted object, you must store the AnimControl pointer in a PT(AnimControl) object, and not an AnimControl * object. This is necessary to retain the reference count and prevent the AnimControl from being inadvertently destructed before you can use it.

David

Thanks David!! That resolved the issue. I am posting the class for someone who may find it useful. The code is not in a presentable state, but it works.

class Jester
{
	public:
		Jester(WindowFramework *window, NodePath parent, string path)
		{
			jester = window->load_model(parent, path);
		}

	private:
		NodePath jester;
		char* animationName;
		AnimControlCollection animControls;
	public:
		NodePath getJesterNodepath()
		{
			return jester;
		}

		void setJester(NodePath model)
		{
			jester = model;
		}

		void reparentTo(NodePath parent)
		{
			jester.reparent_to(parent);
		}
		
		void loadAnimation(WindowFramework *window, char* animationName)
		{
			this->animationName = animationName;
			window->load_model(this->jester, animationName);

			//Auto bind the animations to controls
			auto_bind(this->jester.node(), this->animControls, PartGroup::HMF_ok_part_extra | PartGroup::HMF_ok_anim_extra | PartGroup::HMF_ok_wrong_root_name); 

		}

		char* getAnimationName()
		{
			return animationName;
		}

		void setPlayRate(float rate)
		{
			for (int i=0; i<animControls.get_num_anims(); i++)
				animControls.get_anim(i)->set_play_rate(rate);
		}

		void play()
		{
			for (int i=0; i<animControls.get_num_anims(); i++)
				animControls.get_anim(i)->play();
		}

		void setLoop(bool isLoop)
		{
			for (int i=0; i<animControls.get_num_anims(); i++)
				animControls.get_anim(i)->loop(isLoop);
		}

		AnimControlCollection getAnims()
		{
			return animControls;
		}
};

Calls-

Jester *j = new Jester(window, framework.get_models(), "../../models/jester_violin.egg" );
j->reparentTo(window->get_render());
j->getJesterNodepath().set_scale(0.1);
j->getJesterNodepath().set_pos(0,0,2);
j->loadAnimation(window, "../../models/jester_violin_anim.egg");
j->setLoop(true);
j->setPlayRate(0.1);
j->play();