Panda3D
|
00001 // Filename: asyncTaskSequence.cxx 00002 // Created by: drose (04Oct08) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #include "asyncTaskSequence.h" 00016 00017 TypeHandle AsyncTaskSequence::_type_handle; 00018 00019 //////////////////////////////////////////////////////////////////// 00020 // Function: AsyncTaskSequence::Constructor 00021 // Access: Published 00022 // Description: 00023 //////////////////////////////////////////////////////////////////// 00024 AsyncTaskSequence:: 00025 AsyncTaskSequence(const string &name) : 00026 AsyncTask(name), 00027 _repeat_count(0), 00028 _task_index(0) 00029 { 00030 } 00031 00032 //////////////////////////////////////////////////////////////////// 00033 // Function: AsyncTaskSequence::Destructor 00034 // Access: Published, Virtual 00035 // Description: 00036 //////////////////////////////////////////////////////////////////// 00037 AsyncTaskSequence:: 00038 ~AsyncTaskSequence() { 00039 set_current_task(NULL, true); 00040 } 00041 00042 //////////////////////////////////////////////////////////////////// 00043 // Function: AsyncTaskSequence::is_runnable 00044 // Access: Protected, Virtual 00045 // Description: Override this function to return true if the task can 00046 // be successfully executed, false if it cannot. Mainly 00047 // intended as a sanity check when attempting to add the 00048 // task to a task manager. 00049 // 00050 // This function is called with the lock held. 00051 //////////////////////////////////////////////////////////////////// 00052 bool AsyncTaskSequence:: 00053 is_runnable() { 00054 return (get_num_tasks() > 0); 00055 } 00056 00057 //////////////////////////////////////////////////////////////////// 00058 // Function: AsyncTaskSequence::do_task 00059 // Access: Protected, Virtual 00060 // Description: Override this function to do something useful for the 00061 // task. 00062 // 00063 // This function is called with the lock *not* held. 00064 //////////////////////////////////////////////////////////////////// 00065 AsyncTask::DoneStatus AsyncTaskSequence:: 00066 do_task() { 00067 // Clear the delay that might have been set from a previous wait. 00068 _delay = 0.0; 00069 _has_delay = false; 00070 00071 if (_task_index >= get_num_tasks()) { 00072 // Ran off the end of the task list. 00073 set_current_task(NULL, true); 00074 _task_index = 0; 00075 if (_task_index >= get_num_tasks()) { 00076 return DS_done; 00077 } 00078 if (_repeat_count > 0) { 00079 --_repeat_count; 00080 } 00081 if (_repeat_count != 0) { 00082 return DS_cont; 00083 } 00084 return DS_done; 00085 } 00086 00087 AsyncTask *task = get_task(_task_index); 00088 set_current_task(task, true); 00089 nassertr(_current_task != (AsyncTask *)NULL, DS_exit); 00090 00091 DoneStatus result = _current_task->do_task(); 00092 switch (result) { 00093 case DS_again: 00094 case DS_pause: 00095 // The task wants to sleep for a period of time. 00096 { 00097 double now = _manager->_clock->get_frame_time(); 00098 _current_task->_start_time = now + _current_task->_delay; 00099 00100 _delay = _current_task->_delay; 00101 _has_delay = _current_task->_has_delay; 00102 00103 if (result == DS_pause) { 00104 // When it wakes up, move on to the next task. 00105 ++_task_index; 00106 } 00107 } 00108 return DS_again; 00109 00110 case DS_done: 00111 // Go on to the next task. 00112 ++_task_index; 00113 return DS_cont; 00114 00115 case DS_cont: 00116 case DS_pickup: 00117 case DS_exit: 00118 case DS_interrupt: 00119 // Just return these results through. 00120 return result; 00121 } 00122 00123 // Shouldn't get here. 00124 nassertr(false, DS_exit); 00125 return DS_exit; 00126 } 00127 00128 //////////////////////////////////////////////////////////////////// 00129 // Function: AsyncTaskSequence::upon_birth 00130 // Access: Protected, Virtual 00131 // Description: Override this function to do something useful when the 00132 // task has been added to the active queue. 00133 // 00134 // This function is called with the lock held. You may 00135 // temporarily release if it necessary, but be sure to 00136 // return with it held. 00137 //////////////////////////////////////////////////////////////////// 00138 void AsyncTaskSequence:: 00139 upon_birth(AsyncTaskManager *manager) { 00140 AsyncTask::upon_birth(manager); 00141 _task_index = 0; 00142 set_current_task(NULL, true); 00143 } 00144 00145 //////////////////////////////////////////////////////////////////// 00146 // Function: AsyncTaskSequence::upon_death 00147 // Access: Protected, Virtual 00148 // Description: Override this function to do something useful when the 00149 // task has been removed from the active queue. The 00150 // parameter clean_exit is true if the task has been 00151 // removed because it exited normally (returning 00152 // DS_done), or false if it was removed for some other 00153 // reason (e.g. AsyncTaskManager::remove()). By the 00154 // time this method is called, _manager has been 00155 // cleared, so the parameter manager indicates the 00156 // original AsyncTaskManager that owned this task. 00157 // 00158 // The normal behavior is to throw the done_event only 00159 // if clean_exit is true. 00160 // 00161 // This function is called with the lock held. You may 00162 // temporarily release if it necessary, but be sure to 00163 // return with it held. 00164 //////////////////////////////////////////////////////////////////// 00165 void AsyncTaskSequence:: 00166 upon_death(AsyncTaskManager *manager, bool clean_exit) { 00167 AsyncTask::upon_death(manager, clean_exit); 00168 set_current_task(NULL, clean_exit); 00169 } 00170 00171 //////////////////////////////////////////////////////////////////// 00172 // Function: AsyncTaskSequence::set_current_task 00173 // Access: Private 00174 // Description: Sets the current executing task. If NULL, sets the 00175 // current task to NULL. 00176 //////////////////////////////////////////////////////////////////// 00177 void AsyncTaskSequence:: 00178 set_current_task(AsyncTask *task, bool clean_exit) { 00179 if (_current_task == task) { 00180 return; 00181 } 00182 00183 if (_current_task != (AsyncTask *)NULL) { 00184 nassertv(_current_task->_state == S_active_nested); 00185 nassertv(_current_task->_manager == _manager || _manager == NULL); 00186 _current_task->_state = S_inactive; 00187 _current_task->_manager = NULL; 00188 _current_task->upon_death(_manager, clean_exit); 00189 } 00190 00191 _current_task = task; 00192 00193 if (_current_task != (AsyncTask *)NULL) { 00194 nassertv(_current_task->_state == S_inactive); 00195 nassertv(_current_task->_manager == NULL); 00196 _current_task->upon_birth(_manager); 00197 nassertv(_current_task->_state == S_inactive); 00198 nassertv(_current_task->_manager == NULL); 00199 _current_task->_manager = _manager; 00200 _current_task->_state = S_active_nested; 00201 00202 double now = _manager->_clock->get_frame_time(); 00203 task->_start_time = now; 00204 task->_start_frame = _manager->_clock->get_frame_count(); 00205 } 00206 }