|
|
@@ -0,0 +1,193 @@
|
|
|
+// Filename: asyncTaskSequence.cxx
|
|
|
+// Created by: drose (04Oct08)
|
|
|
+//
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+//
|
|
|
+// PANDA 3D SOFTWARE
|
|
|
+// Copyright (c) Carnegie Mellon University. All rights reserved.
|
|
|
+//
|
|
|
+// All use of this software is subject to the terms of the revised BSD
|
|
|
+// license. You should have received a copy of this license along
|
|
|
+// with this source code in a file named "LICENSE."
|
|
|
+//
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+
|
|
|
+#include "asyncTaskSequence.h"
|
|
|
+
|
|
|
+TypeHandle AsyncTaskSequence::_type_handle;
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: AsyncTaskSequence::Constructor
|
|
|
+// Access: Published
|
|
|
+// Description:
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+AsyncTaskSequence::
|
|
|
+AsyncTaskSequence(const string &name) :
|
|
|
+ AsyncTask(name),
|
|
|
+ _repeat_count(0),
|
|
|
+ _task_index(0)
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: AsyncTaskSequence::Destructor
|
|
|
+// Access: Published, Virtual
|
|
|
+// Description:
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+AsyncTaskSequence::
|
|
|
+~AsyncTaskSequence() {
|
|
|
+ set_current_task(NULL, true);
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: AsyncTaskSequence::is_runnable
|
|
|
+// Access: Protected, Virtual
|
|
|
+// Description: Override this function to return true if the task can
|
|
|
+// be successfully executed, false if it cannot. Mainly
|
|
|
+// intended as a sanity check when attempting to add the
|
|
|
+// task to a task manager.
|
|
|
+//
|
|
|
+// This function is called with the lock held.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+bool AsyncTaskSequence::
|
|
|
+is_runnable() {
|
|
|
+ return (get_num_tasks() > 0);
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: AsyncTaskSequence::do_task
|
|
|
+// Access: Protected, Virtual
|
|
|
+// Description: Override this function to do something useful for the
|
|
|
+// task.
|
|
|
+//
|
|
|
+// This function is called with the lock *not* held.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+AsyncTask::DoneStatus AsyncTaskSequence::
|
|
|
+do_task() {
|
|
|
+ // Clear the delay that might have been set from a previous wait.
|
|
|
+ _delay = 0.0;
|
|
|
+ _has_delay = false;
|
|
|
+
|
|
|
+ if (_task_index >= get_num_tasks()) {
|
|
|
+ // Ran off the end of the task list.
|
|
|
+ set_current_task(NULL, true);
|
|
|
+ _task_index = 0;
|
|
|
+ if (_task_index >= get_num_tasks()) {
|
|
|
+ return DS_done;
|
|
|
+ }
|
|
|
+ if (_repeat_count > 0) {
|
|
|
+ --_repeat_count;
|
|
|
+ }
|
|
|
+ if (_repeat_count != 0) {
|
|
|
+ return DS_cont;
|
|
|
+ }
|
|
|
+ return DS_done;
|
|
|
+ }
|
|
|
+
|
|
|
+ AsyncTask *task = get_task(_task_index);
|
|
|
+ set_current_task(task, true);
|
|
|
+ nassertr(_current_task != (AsyncTask *)NULL, DS_exit);
|
|
|
+
|
|
|
+ DoneStatus result = _current_task->do_task();
|
|
|
+ switch (result) {
|
|
|
+ case DS_again:
|
|
|
+ case DS_pause:
|
|
|
+ // The task wants to sleep for a period of time.
|
|
|
+ {
|
|
|
+ double now = _manager->_clock->get_frame_time();
|
|
|
+ _current_task->_start_time = now + _current_task->_delay;
|
|
|
+
|
|
|
+ _delay = _current_task->_delay;
|
|
|
+ _has_delay = _current_task->_has_delay;
|
|
|
+
|
|
|
+ if (result == DS_pause) {
|
|
|
+ // When it wakes up, move on to the next task.
|
|
|
+ ++_task_index;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return DS_again;
|
|
|
+
|
|
|
+ case DS_done:
|
|
|
+ // Go on to the next task.
|
|
|
+ ++_task_index;
|
|
|
+ return DS_cont;
|
|
|
+
|
|
|
+ case DS_cont:
|
|
|
+ case DS_pickup:
|
|
|
+ case DS_exit:
|
|
|
+ case DS_abort:
|
|
|
+ // Just return these results through.
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: AsyncTaskSequence::upon_birth
|
|
|
+// Access: Protected, Virtual
|
|
|
+// Description: Override this function to do something useful when the
|
|
|
+// task has been added to the active queue.
|
|
|
+//
|
|
|
+// This function is called with the lock held. You may
|
|
|
+// temporarily release if it necessary, but be sure to
|
|
|
+// return with it held.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+void AsyncTaskSequence::
|
|
|
+upon_birth() {
|
|
|
+ AsyncTask::upon_birth();
|
|
|
+ _task_index = 0;
|
|
|
+ set_current_task(NULL, true);
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: AsyncTaskSequence::upon_death
|
|
|
+// Access: Protected, Virtual
|
|
|
+// Description: Override this function to do something useful when the
|
|
|
+// task has been removed from the active queue. The
|
|
|
+// parameter clean_exit is true if the task has been
|
|
|
+// removed because it exited normally (returning
|
|
|
+// DS_done), or false if it was removed for some other
|
|
|
+// reason (e.g. AsyncTaskManager::remove()).
|
|
|
+//
|
|
|
+// The normal behavior is to throw the done_event only
|
|
|
+// if clean_exit is true.
|
|
|
+//
|
|
|
+// This function is called with the lock held. You may
|
|
|
+// temporarily release if it necessary, but be sure to
|
|
|
+// return with it held.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+void AsyncTaskSequence::
|
|
|
+upon_death(bool clean_exit) {
|
|
|
+ AsyncTask::upon_death(clean_exit);
|
|
|
+ set_current_task(NULL, clean_exit);
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: AsyncTaskSequence::set_current_task
|
|
|
+// Access: Private
|
|
|
+// Description: Sets the current executing task. If NULL, sets the
|
|
|
+// current task to NULL.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+void AsyncTaskSequence::
|
|
|
+set_current_task(AsyncTask *task, bool clean_exit) {
|
|
|
+ if (_current_task == task) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (_current_task != (AsyncTask *)NULL) {
|
|
|
+ nassertv(_current_task->_state == S_active_nested);
|
|
|
+ nassertv(_current_task->_manager == _manager || _manager == NULL);
|
|
|
+ _current_task->_state = S_inactive;
|
|
|
+ _current_task->upon_death(clean_exit);
|
|
|
+ _current_task->_manager = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ _current_task = task;
|
|
|
+
|
|
|
+ if (_current_task != (AsyncTask *)NULL) {
|
|
|
+ nassertv(_current_task->_state == S_inactive);
|
|
|
+ nassertv(_current_task->_manager == NULL);
|
|
|
+ _current_task->_manager = _manager;
|
|
|
+ _current_task->_state = S_active_nested;
|
|
|
+ _current_task->upon_birth();
|
|
|
+ }
|
|
|
+}
|