Tasks in C++

Hey,

Does anyone know how tasks work in Panda3D in C++?

Thanks.

They don’t. The task manager is fully implemented in Python.

There does exist such a thing as an AsyncTaskManager in C++, but it’s not (yet) as fully general as Python’s task manager. It’s used just to load models asynchronously.

One day, perhaps, the AsyncTaskManager will be expanded to make it more generally useful. Until then, you have to use your own C++ constructs to implement tasks.

David

how?

i can’t alter the main_loop() can I ?

Um, the same way you would do any other C++ program?

Just think of Panda as a rendering engine in this case. Whenever you’re ready to render, call PandaFramework::do_frame()–don’t use the main_loop() call.

In between calls to do_frame(), do whatever you want.

David

OK, thanks, I’ll orc something out and put it in the manual.

Another two questions:

  1. what about events?

  2. I use this code:

  //window and model init
  while(true) {
    //task stuff here
    framework.do_frame(current_thread);
  }
  //close the window framework
  framework.close_framework();
  return (0);

Now, when I close the window again, the program keeps running.
How to terminate it when the window gets closed?

Don’t forget to read the C++ comments embedded in the code. For instance, the comment block for PandaFramework::do_frame() says:

////////////////////////////////////////////////////////////////////
//     Function: PandaFramework::do_frame
//       Access: Public, Virtual
//  Description: Renders one frame and performs all associated
//               processing.  Returns true if we should continue
//               rendering, false if we should exit.  This is normally
//               called only from main_loop().
////////////////////////////////////////////////////////////////////

You and also often answer questions like this by reading the code itself. For instance, the definition of PandaFramework::main_loop() is:

void PandaFramework::
main_loop() {
  Thread *current_thread = Thread::get_current_thread();
  while (do_frame(current_thread)) {
  }
}

David

Thanks David, that worked like a charm! :slight_smile:

Another thing: what about events? Do I have to program them myself? Or is this also supported?

PandaFramework has an EventHandler class that you can get a handle to. See the C++ comments in the EventHandler class for the add_hook() method, which you can use to associate your C++ function with an event.

You can also include “throw_event.h”, which gives you the throw_event() global function, for throwing any arbitrary event you like. Of course, keypress events will work as they do in Python.

David

Thanks!

Ok, one more question:
How to load an model in C++ with animations? There’s no such thing as Actors in C++, because the Actor class is written in Python.
I can’t really seem to find out how pview does it…

Look for auto_bind().

David

Thanks, david.
I’ve been trying some things with auto_bind, looked at the source etc.

But I can’t figure out how to call auto_bind? window->auto_bind? nodepath.auto_bind? framework.auto_bind? none of these work.

Did you see the way it is being called in pview?

void WindowFramework::
loop_animations(int hierarchy_match_flags) {
  // If we happened to load up both a character file and its matching
  // animation file, attempt to bind them together now and start the
  // animations looping.
  auto_bind(get_render().node(), _anim_controls, hierarchy_match_flags);
  _anim_controls.loop_all(true);
}

David

Thanks, drwr, I didn’t notice that line. I didn’t know I had to load the animation as a separate model. I got it to work now.
I hope I don’t bother you too much, but I have another small question.
What excactly is the hierarchy_match_flags in pview?
window->loop_animations(hierarchy_match_flags) takes any value as parameter.

If you follow through the code, you can see that WindowFramework::loop_animations() passes this value to auto_bind(), which passes it to PartBundle::bind_anim(), which contains the following explanatory comment:

////////////////////////////////////////////////////////////////////
//     Function: PartBundle::bind_anim
//       Access: Published
//  Description: Binds the animation to the bundle, if possible, and
//               returns a new AnimControl that can be used to start
//               and stop the animation.  If the anim hierarchy does
//               not match the part hierarchy, returns NULL.
//
//               If hierarchy_match_flags is 0, only an exact match is
//               accepted; otherwise, it may contain a union of
//               PartGroup::HierarchyMatchFlags values indicating
//               conditions that will be tolerated (but warnings will
//               still be issued).
//
//               If subset is specified, it restricts the binding only
//               to the named subtree of joints.
//
//               The AnimControl is not stored within the PartBundle;
//               it is the user's responsibility to maintain the
//               pointer.  The animation will automatically unbind
//               itself when the AnimControl destructs (i.e. its
//               reference count goes to zero).
////////////////////////////////////////////////////////////////////

And then if you look at the definition of PartGroup::HierarchyMatchFlags in partGroup.h, you also see the following:

  // This enum defines bits which may be passed into check_hierarchy()
  // and PartBundle::bind_anim() to allow an inexact match of channel
  // hierarchies.  This specifies conditions that we don't care about
  // enforcing.
  enum HierarchyMatchFlags {
    HMF_ok_part_extra          = 0x01,
    HMF_ok_anim_extra          = 0x02,
    HMF_ok_wrong_root_name     = 0x04,
  };

So, this variable contains instructions about how to handle an animation hierarchy that doesn’t exactly match the character hierarchy it is being bound to.

David

Thanks again a million times, David.
I’m going to update the “Loading and Animating the Panda Model” page at the manual soon.

now the last page.

Tell me, HprIntervals and PosIntervals aren’t supported in C++ either, are they?
Looked for them in the source, nop, couldn’t find them.

They exist, but they are all just variants on the CLerpNodePathInterval, which is defined in direct/src/interval. Create a CLerpNodePathInterval, and then call the appropriate set_start_pos/hpr/quat/scale() and set_end_pos/hpr/quat_scale() methods.

David

Hmm. Sorry to bother you again, but I’m getting now no errors with compiling, but I do get errors when linking:

tutorial.o: In function `main':
tutorial.cxx:(.text+0x6a1): undefined reference to `CLerpNodePathInterval::CLerpNodePathInterval(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, double, CLerpInterval::BlendType, bool, bool, NodePath const&, NodePath const&)'
tutorial.cxx:(.text+0x7ab): undefined reference to `CInterval::loop(double, double, double)'
tutorial.o: In function `CLerpInterval::get_type() const':
tutorial.cxx:(.text._ZNK13CLerpInterval8get_typeEv[CLerpInterval::get_type() const]+0x13): undefined reference to `CLerpInterval::_type_handle'
tutorial.o: In function `CLerpInterval::~CLerpInterval()':
tutorial.cxx:(.text._ZN13CLerpIntervalD0Ev[CLerpInterval::~CLerpInterval()]+0x29): undefined reference to `CInterval::~CInterval()'

....and a lot more errors like this...

Am I messing up pointers or something like that? Here is my code:

    //setup the movement intervals
  CLerpNodePathInterval pandaPosInterval1("pandaPosInterval1",13.0,CLerpInterval::BT_no_blend,true,false,pandaActor,window->get_render());
  pandaPosInterval1.set_start_pos(LPoint3f(0,10,0));
  pandaPosInterval1.set_end_pos(LPoint3f(0,-10,0));
  pandaPosInterval1.loop();

And, I have another question, if you don’t mind.
How about sequences/parallels? I’ve tried looking at CInterval, since it claims to be able to have a “collection of nested intervals that will be performed at some specific time or over a period of time.” but I wouldn’t have an idea how that system works.

The C++ interval code is in the Direct tree. You need to be sure you are linking with libdirect.dll (or libp3ddirect.dll, or whatever it is that makepanda renamed it to).

To make a Sequence or Parallel, look at cMetaInterval.h. It may also be helpful to look at the Python code in MetalInterval.py and see how the Python Sequence and Parallel classes work. You’ll construct a CMetaInterval, and add a bunch of nested intervals to it. For a Sequence, each of them will be added with RS_previous_end to start them at the end of the previous interval. For a Parallel, add them with RS_previous_begin to start them at the beginning of the previous interval.

David