From 4beba6ca6f45506a8dd1175fda872478a0a06a66 Mon Sep 17 00:00:00 2001 From: David Rose Date: Fri, 3 Oct 2008 20:30:07 +0000 Subject: [PATCH] integrate pview with new task manager --- panda/src/event/Sources.pp | 3 + panda/src/event/asyncTask.cxx | 27 +++++ panda/src/event/asyncTask.h | 3 + panda/src/event/asyncTaskManager.h | 1 - panda/src/event/config_event.cxx | 2 + panda/src/event/event_composite1.cxx | 1 + panda/src/event/genericAsyncTask.I | 103 ++++++++++++++++ panda/src/event/genericAsyncTask.cxx | 123 +++++++++++++++++++ panda/src/event/genericAsyncTask.h | 83 +++++++++++++ panda/src/event/pythonTask.cxx | 8 +- panda/src/framework/pandaFramework.I | 16 ++- panda/src/framework/pandaFramework.cxx | 149 +++++++++++++++++++----- panda/src/framework/pandaFramework.h | 16 ++- panda/src/framework/windowFramework.cxx | 9 +- panda/src/framework/windowFramework.h | 3 +- 15 files changed, 507 insertions(+), 40 deletions(-) create mode 100644 panda/src/event/genericAsyncTask.I create mode 100644 panda/src/event/genericAsyncTask.cxx create mode 100644 panda/src/event/genericAsyncTask.h diff --git a/panda/src/event/Sources.pp b/panda/src/event/Sources.pp index d89e1aec1b..237598750e 100644 --- a/panda/src/event/Sources.pp +++ b/panda/src/event/Sources.pp @@ -15,6 +15,7 @@ config_event.h \ buttonEvent.I buttonEvent.h \ buttonEventList.I buttonEventList.h \ + genericAsyncTask.h genericAsyncTask.I \ pointerEvent.I pointerEvent.h \ pointerEventList.I pointerEventList.h \ pythonTask.h pythonTask.I \ @@ -30,6 +31,7 @@ asyncTaskManager.cxx \ buttonEvent.cxx \ buttonEventList.cxx \ + genericAsyncTask.cxx \ pointerEvent.cxx \ pointerEventList.cxx \ pythonTask.cxx \ @@ -44,6 +46,7 @@ asyncTaskManager.h asyncTaskManager.I \ buttonEvent.I buttonEvent.h \ buttonEventList.I buttonEventList.h \ + genericAsyncTask.cxx \ pointerEvent.I pointerEvent.h \ pointerEventList.I pointerEventList.h \ pythonTask.h pythonTask.I \ diff --git a/panda/src/event/asyncTask.cxx b/panda/src/event/asyncTask.cxx index db8248e653..d984f86ad8 100644 --- a/panda/src/event/asyncTask.cxx +++ b/panda/src/event/asyncTask.cxx @@ -466,3 +466,30 @@ upon_death(bool clean_exit) { throw_event(event); } } + +//////////////////////////////////////////////////////////////////// +// Function: AsyncTask::release_lock +// Access: Protected +// Description: Releases the task lock. This is intended to be +// used within callback functions, for instance +// upon_birth() or upon_death(), as needed to release +// the lock for processing. Be sure to grab it again +// before returning. +//////////////////////////////////////////////////////////////////// +void AsyncTask:: +release_lock() { + _manager->_lock.release(); +} + +//////////////////////////////////////////////////////////////////// +// Function: AsyncTask::grab_lock +// Access: Protected +// Description: Releases the task lock. This is intended to be +// used within callback functions, to grab the lock +// after a previous call to release_lock(). +//////////////////////////////////////////////////////////////////// +void AsyncTask:: +grab_lock() { + _manager->_lock.lock(); +} + diff --git a/panda/src/event/asyncTask.h b/panda/src/event/asyncTask.h index b4dbcee66a..f0c4ff113e 100644 --- a/panda/src/event/asyncTask.h +++ b/panda/src/event/asyncTask.h @@ -117,6 +117,9 @@ protected: virtual void upon_birth(); virtual void upon_death(bool clean_exit); + void release_lock(); + void grab_lock(); + protected: AtomicAdjust::Integer _task_id; string _chain_name; diff --git a/panda/src/event/asyncTaskManager.h b/panda/src/event/asyncTaskManager.h index 7fb073bd50..ab2cd646d5 100644 --- a/panda/src/event/asyncTaskManager.h +++ b/panda/src/event/asyncTaskManager.h @@ -156,7 +156,6 @@ private: friend class AsyncTaskChain; friend class AsyncTaskChain::AsyncTaskChainThread; friend class AsyncTask; - friend class PythonTask; }; INLINE ostream &operator << (ostream &out, const AsyncTaskManager &manager) { diff --git a/panda/src/event/config_event.cxx b/panda/src/event/config_event.cxx index 32a7b6c1e2..221c4a1c40 100644 --- a/panda/src/event/config_event.cxx +++ b/panda/src/event/config_event.cxx @@ -20,6 +20,7 @@ #include "event.h" #include "eventHandler.h" #include "eventParameter.h" +#include "genericAsyncTask.h" #include "pointerEventList.h" #include "pythonTask.h" @@ -43,6 +44,7 @@ ConfigureFn(config_event) { EventStoreString::init_type("EventStoreString"); EventStoreWstring::init_type("EventStoreWstring"); EventStoreTypedRefCount::init_type(); + GenericAsyncTask::init_type(); PythonTask::init_type(); ButtonEventList::register_with_read_factory(); diff --git a/panda/src/event/event_composite1.cxx b/panda/src/event/event_composite1.cxx index ca66ff6c8b..d3e992264a 100644 --- a/panda/src/event/event_composite1.cxx +++ b/panda/src/event/event_composite1.cxx @@ -4,6 +4,7 @@ #include "asyncTaskManager.cxx" #include "buttonEvent.cxx" #include "buttonEventList.cxx" +#include "genericAsyncTask.cxx" #include "pointerEvent.cxx" #include "pointerEventList.cxx" #include "pythonTask.cxx" diff --git a/panda/src/event/genericAsyncTask.I b/panda/src/event/genericAsyncTask.I new file mode 100644 index 0000000000..fc9317da93 --- /dev/null +++ b/panda/src/event/genericAsyncTask.I @@ -0,0 +1,103 @@ +// Filename: genericAsyncTask.I +// Created by: drose (03Oct08) +// +//////////////////////////////////////////////////////////////////// +// +// 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." +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: GenericAsyncTask::set_function +// Access: Published +// Description: Replaces the function that is called when the task +// runs. +//////////////////////////////////////////////////////////////////// +INLINE void GenericAsyncTask:: +set_function(GenericAsyncTask::TaskFunc *function) { + _function = function; +} + +//////////////////////////////////////////////////////////////////// +// Function: GenericAsyncTask::get_function +// Access: Published +// Description: Returns the function that is called when the task +// runs. +//////////////////////////////////////////////////////////////////// +INLINE GenericAsyncTask::TaskFunc *GenericAsyncTask:: +get_function() const { + return _function; +} + +//////////////////////////////////////////////////////////////////// +// Function: GenericAsyncTask::set_upon_birth +// Access: Published +// Description: Replaces the function that is called when the task +// begins. This is an optional function. +//////////////////////////////////////////////////////////////////// +INLINE void GenericAsyncTask:: +set_upon_birth(GenericAsyncTask::BirthFunc *upon_birth) { + _upon_birth = upon_birth; +} + +//////////////////////////////////////////////////////////////////// +// Function: GenericAsyncTask::get_upon_birth +// Access: Published +// Description: Returns the function that is called when the task +// begins, or NULL if the function is not defined. +//////////////////////////////////////////////////////////////////// +INLINE GenericAsyncTask::BirthFunc *GenericAsyncTask:: +get_upon_birth() const { + return _upon_birth; +} + +//////////////////////////////////////////////////////////////////// +// Function: GenericAsyncTask::set_upon_death +// Access: Published +// Description: Replaces the function that is called when the task +// ends. This is an optional function. +//////////////////////////////////////////////////////////////////// +INLINE void GenericAsyncTask:: +set_upon_death(GenericAsyncTask::DeathFunc *upon_death) { + _upon_death = upon_death; +} + +//////////////////////////////////////////////////////////////////// +// Function: GenericAsyncTask::get_upon_death +// Access: Published +// Description: Returns the function that is called when the task +// ends, or NULL if the function is not defined. +//////////////////////////////////////////////////////////////////// +INLINE GenericAsyncTask::DeathFunc *GenericAsyncTask:: +get_upon_death() const { + return _upon_death; +} + +//////////////////////////////////////////////////////////////////// +// Function: GenericAsyncTask::set_user_data +// Access: Published +// Description: Replaces the void pointer that is passed to the task +// function. This is any arbitrary pointer; the task +// object does no processing on it. +//////////////////////////////////////////////////////////////////// +INLINE void GenericAsyncTask:: +set_user_data(void *user_data) { + _user_data = user_data; +} + +//////////////////////////////////////////////////////////////////// +// Function: GenericAsyncTask::get_user_data +// Access: Published +// Description: Returns the void pointer that is passed to the task +// function. +//////////////////////////////////////////////////////////////////// +INLINE void *GenericAsyncTask:: +get_user_data() const { + return _user_data; +} diff --git a/panda/src/event/genericAsyncTask.cxx b/panda/src/event/genericAsyncTask.cxx new file mode 100644 index 0000000000..f3577161ed --- /dev/null +++ b/panda/src/event/genericAsyncTask.cxx @@ -0,0 +1,123 @@ +// Filename: genericAsyncTask.cxx +// Created by: drose (03Oct08) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "genericAsyncTask.h" +#include "pnotify.h" + +TypeHandle GenericAsyncTask::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: GenericAsyncTask::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +GenericAsyncTask:: +GenericAsyncTask(const string &name) : + AsyncTask(name) +{ + _function = NULL; + _upon_birth = NULL; + _upon_death = NULL; + _user_data = NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: GenericAsyncTask::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +GenericAsyncTask:: +GenericAsyncTask(const string &name, GenericAsyncTask::TaskFunc *function, void *user_data) : + AsyncTask(name), + _function(function), + _user_data(user_data) +{ + _upon_birth = NULL; + _upon_death = NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: GenericAsyncTask::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 GenericAsyncTask:: +is_runnable() { + return _function != NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: GenericAsyncTask::do_task +// Access: Protected, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +AsyncTask::DoneStatus GenericAsyncTask:: +do_task() { + nassertr(_function != NULL, DS_abort); + return (*_function)(this, _user_data); +} + +//////////////////////////////////////////////////////////////////// +// Function: GenericAsyncTask::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 GenericAsyncTask:: +upon_birth() { + AsyncTask::upon_birth(); + + if (_upon_birth != NULL) { + release_lock(); + (*_upon_birth)(this, _user_data); + grab_lock(); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: GenericAsyncTask::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 GenericAsyncTask:: +upon_death(bool clean_exit) { + AsyncTask::upon_death(clean_exit); + + if (_upon_death != NULL) { + release_lock(); + (*_upon_death)(this, clean_exit, _user_data); + grab_lock(); + } +} diff --git a/panda/src/event/genericAsyncTask.h b/panda/src/event/genericAsyncTask.h new file mode 100644 index 0000000000..15e2d7e783 --- /dev/null +++ b/panda/src/event/genericAsyncTask.h @@ -0,0 +1,83 @@ +// Filename: genericAsyncTask.h +// Created by: drose (16Sep08) +// +//////////////////////////////////////////////////////////////////// +// +// 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." +// +//////////////////////////////////////////////////////////////////// + +#ifndef GENERICASYNCTASK_H +#define GENERICASYNCTASK_H + +#include "pandabase.h" + +#include "asyncTask.h" + +//////////////////////////////////////////////////////////////////// +// Class : GenericAsyncTask +// Description : Associates a generic C-style function pointer with an +// AsyncTask object. You can use this when you want to +// create an AsyncTask without having to subclass. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA_PIPELINE GenericAsyncTask : public AsyncTask { +public: + typedef DoneStatus TaskFunc(GenericAsyncTask *task, void *user_data); + typedef void BirthFunc(GenericAsyncTask *task, void *user_data); + typedef void DeathFunc(GenericAsyncTask *task, bool clean_exit, void *user_data); + + GenericAsyncTask(const string &name = string()); + GenericAsyncTask(const string &name, TaskFunc *function, void *user_data); + ALLOC_DELETED_CHAIN(GenericAsyncTask); + + INLINE void set_function(TaskFunc *function); + INLINE TaskFunc *get_function() const; + + INLINE void set_upon_birth(BirthFunc *function); + INLINE BirthFunc *get_upon_birth() const; + + INLINE void set_upon_death(DeathFunc *function); + INLINE DeathFunc *get_upon_death() const; + + INLINE void set_user_data(void *user_data); + INLINE void *get_user_data() const; + +protected: + virtual bool is_runnable(); + virtual DoneStatus do_task(); + virtual void upon_birth(); + virtual void upon_death(bool clean_exit); + +private: + TaskFunc *_function; + BirthFunc *_upon_birth; + DeathFunc *_upon_death; + void *_user_data; + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + AsyncTask::init_type(); + register_type(_type_handle, "GenericAsyncTask", + AsyncTask::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; +}; + +#include "genericAsyncTask.I" + +#endif + diff --git a/panda/src/event/pythonTask.cxx b/panda/src/event/pythonTask.cxx index 004f246c95..312b036a1e 100644 --- a/panda/src/event/pythonTask.cxx +++ b/panda/src/event/pythonTask.cxx @@ -476,7 +476,7 @@ upon_birth() { AsyncTask::upon_birth(); if (_owner != Py_None) { - _manager->_lock.release(); + release_lock(); #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS) // Use PyGILState to protect this asynchronous call. PyGILState_STATE gstate; @@ -488,7 +488,7 @@ upon_birth() { #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS) PyGILState_Release(gstate); #endif - _manager->_lock.lock(); + grab_lock(); } } @@ -514,7 +514,7 @@ upon_death(bool clean_exit) { AsyncTask::upon_death(clean_exit); if (_owner != Py_None && _upon_death != Py_None) { - _manager->_lock.release(); + release_lock(); #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS) // Use PyGILState to protect this asynchronous call. PyGILState_STATE gstate; @@ -527,7 +527,7 @@ upon_death(bool clean_exit) { #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS) PyGILState_Release(gstate); #endif - _manager->_lock.lock(); + grab_lock(); } } diff --git a/panda/src/framework/pandaFramework.I b/panda/src/framework/pandaFramework.I index fc3352608e..2e1bd88ef5 100644 --- a/panda/src/framework/pandaFramework.I +++ b/panda/src/framework/pandaFramework.I @@ -23,7 +23,10 @@ INLINE GraphicsEngine *PandaFramework:: get_graphics_engine() { if (_engine == (GraphicsEngine *)NULL) { - _engine = new GraphicsEngine; + _engine = GraphicsEngine::get_global_ptr(); + PT(GenericAsyncTask) task = new GenericAsyncTask("igloop", task_igloop, this); + task->set_sort(50); + _task_mgr.add(task); } return _engine; } @@ -52,6 +55,17 @@ get_event_handler() { return _event_handler; } +//////////////////////////////////////////////////////////////////// +// Function: PandaFramework::get_task_mgr +// Access: Public +// Description: Returns the Task Manager object that manages tasks in +// the framework. +//////////////////////////////////////////////////////////////////// +INLINE AsyncTaskManager &PandaFramework:: +get_task_mgr() { + return _task_mgr; +} + //////////////////////////////////////////////////////////////////// // Function: PandaFramework::set_window_title // Access: Public diff --git a/panda/src/framework/pandaFramework.cxx b/panda/src/framework/pandaFramework.cxx index 451587ed36..f55eac3f5a 100644 --- a/panda/src/framework/pandaFramework.cxx +++ b/panda/src/framework/pandaFramework.cxx @@ -37,7 +37,8 @@ LoaderOptions PandaFramework::_loader_options; //////////////////////////////////////////////////////////////////// PandaFramework:: PandaFramework() : - _event_handler(*EventHandler::get_global_event_handler()) + _event_handler(*EventHandler::get_global_event_handler()), + _task_mgr(*AsyncTaskManager::get_global_ptr()) { _is_open = false; _made_default_pipe = false; @@ -86,7 +87,18 @@ open_framework(int &argc, char **&argv) { reset_frame_rate(); + { + PT(GenericAsyncTask) task = new GenericAsyncTask("event", task_event, this); + _task_mgr.add(task); + } + _data_root = NodePath("data"); + { + PT(GenericAsyncTask) task = new GenericAsyncTask("data_loop", task_data_loop, this); + task->set_sort(-50); + _task_mgr.add(task); + } + _highlight_wireframe = NodePath("wireframe"); _highlight_wireframe.set_render_mode_wireframe(1); _highlight_wireframe.set_texture_off(1); @@ -98,12 +110,20 @@ open_framework(int &argc, char **&argv) { // playing. _recorder = new RecorderController; _recorder->begin_playback(Filename::from_os_specific(playback_session)); + + PT(GenericAsyncTask) task = new GenericAsyncTask("play_frame", task_play_frame, this); + task->set_sort(55); + _task_mgr.add(task); } else if (!record_session.empty()) { // If the config file so indicates, create a recorder and start it // recording. _recorder = new RecorderController; _recorder->begin_record(Filename::from_os_specific(record_session)); + + PT(GenericAsyncTask) task = new GenericAsyncTask("record_frame", task_record_frame, this); + task->set_sort(45); + _task_mgr.add(task); } _event_handler.add_hook("window-event", event_window_event, this); @@ -125,7 +145,7 @@ close_framework() { close_all_windows(); // Also close down any other windows that might have been opened. if (_engine != (GraphicsEngine *)NULL) { - delete _engine; + _engine->remove_all_windows(); _engine = NULL; } @@ -766,30 +786,8 @@ enable_default_keys() { bool PandaFramework:: do_frame(Thread *current_thread) { nassertr(_is_open, false); - DataGraphTraverser dg_trav(current_thread); - dg_trav.traverse(_data_root.node()); - throw_event("NewFrame"); - _event_handler.process_events(); - - if (!_screenshot_text.is_empty()) { - double now = ClockObject::get_global_clock()->get_frame_time(); - if (now >= _screenshot_clear_time) { - _screenshot_text.remove_node(); - } - } - - if (_recorder != (RecorderController *)NULL) { - _recorder->record_frame(); - } - - if (_engine != (GraphicsEngine *)NULL) { - _engine->render_frame(); - } - - if (_recorder != (RecorderController *)NULL) { - _recorder->play_frame(); - } + _task_mgr.poll(); return !_exit_flag; } @@ -1338,8 +1336,11 @@ event_f9(const Event *event, void *data) { self->_screenshot_text.reparent_to(wf->get_aspect_2d()); cout << "Screenshot saved: " + output_text + "\n"; - double now = ClockObject::get_global_clock()->get_frame_time(); - self->_screenshot_clear_time = now + 3.0; + // Set a do-later to remove the text in 3 seconds. + self->_task_mgr.remove(self->_task_mgr.find_tasks("clear_text")); + PT(GenericAsyncTask) task = new GenericAsyncTask("clear_text", task_clear_text, self); + task->set_delay(3.0); + self->_task_mgr.add(task); } } @@ -1469,3 +1470,97 @@ event_window_event(const Event *event, void *data) { } } } + +//////////////////////////////////////////////////////////////////// +// Function: PandaFramework::task_data_loop +// Access: Public, Static +// Description: Called once per frame to process the data graph (which +// handles user input via the mouse and keyboard, etc.) +//////////////////////////////////////////////////////////////////// +AsyncTask::DoneStatus PandaFramework:: +task_data_loop(GenericAsyncTask *task, void *data) { + PandaFramework *self = (PandaFramework *)data; + + DataGraphTraverser dg_trav; + dg_trav.traverse(self->_data_root.node()); + + return AsyncTask::DS_cont; +} + +//////////////////////////////////////////////////////////////////// +// Function: PandaFramework::task_event +// Access: Public, Static +// Description: Called once per frame to process the pending events. +//////////////////////////////////////////////////////////////////// +AsyncTask::DoneStatus PandaFramework:: +task_event(GenericAsyncTask *task, void *data) { + PandaFramework *self = (PandaFramework *)data; + + throw_event("NewFrame"); + self->_event_handler.process_events(); + + return AsyncTask::DS_cont; +} + +//////////////////////////////////////////////////////////////////// +// Function: PandaFramework::task_igloop +// Access: Public, Static +// Description: Called once per frame to render the scene. +//////////////////////////////////////////////////////////////////// +AsyncTask::DoneStatus PandaFramework:: +task_igloop(GenericAsyncTask *task, void *data) { + PandaFramework *self = (PandaFramework *)data; + + if (self->_engine != (GraphicsEngine *)NULL) { + self->_engine->render_frame(); + } + + return AsyncTask::DS_cont; +} + +//////////////////////////////////////////////////////////////////// +// Function: PandaFramework::task_record_frame +// Access: Public, Static +// Description: Called once per frame to ask the recorder to record +// the user input data, if enabled. +//////////////////////////////////////////////////////////////////// +AsyncTask::DoneStatus PandaFramework:: +task_record_frame(GenericAsyncTask *task, void *data) { + PandaFramework *self = (PandaFramework *)data; + + if (self->_recorder != (RecorderController *)NULL) { + self->_recorder->record_frame(); + } + + return AsyncTask::DS_cont; +} + +//////////////////////////////////////////////////////////////////// +// Function: PandaFramework::task_play_frame +// Access: Public, Static +// Description: Called once per frame to ask the recorder to play back +// the user input data, if enabled. +//////////////////////////////////////////////////////////////////// +AsyncTask::DoneStatus PandaFramework:: +task_play_frame(GenericAsyncTask *task, void *data) { + PandaFramework *self = (PandaFramework *)data; + + if (self->_recorder != (RecorderController *)NULL) { + self->_recorder->play_frame(); + } + + return AsyncTask::DS_cont; +} + +//////////////////////////////////////////////////////////////////// +// Function: PandaFramework::task_clear_text +// Access: Public, Static +// Description: Called once to remove the screenshot text from onscreen. +//////////////////////////////////////////////////////////////////// +AsyncTask::DoneStatus PandaFramework:: +task_clear_text(GenericAsyncTask *task, void *data) { + PandaFramework *self = (PandaFramework *)data; + + self->clear_text(); + return AsyncTask::DS_cont; +} diff --git a/panda/src/framework/pandaFramework.h b/panda/src/framework/pandaFramework.h index 6e5db30b09..ce51d982b8 100644 --- a/panda/src/framework/pandaFramework.h +++ b/panda/src/framework/pandaFramework.h @@ -26,6 +26,8 @@ #include "graphicsWindow.h" #include "recorderController.h" #include "pointerTo.h" +#include "asyncTaskManager.h" +#include "genericAsyncTask.h" #include "pvector.h" @@ -47,6 +49,7 @@ public: INLINE GraphicsEngine *get_graphics_engine(); INLINE const NodePath &get_data_root() const; INLINE EventHandler &get_event_handler(); + INLINE AsyncTaskManager &get_task_mgr(); NodePath get_mouse(GraphicsWindow *window); void remove_mouse(const GraphicsWindow *window); @@ -148,6 +151,15 @@ public: static void event_window_event(const Event *, void *data); + static AsyncTask::DoneStatus task_data_loop(GenericAsyncTask *task, void *data); + static AsyncTask::DoneStatus task_event(GenericAsyncTask *task, void *data); + static AsyncTask::DoneStatus task_clear_screenshot_text(GenericAsyncTask *task, void *data); + static AsyncTask::DoneStatus task_igloop(GenericAsyncTask *task, void *data); + static AsyncTask::DoneStatus task_record_frame(GenericAsyncTask *task, void *data); + static AsyncTask::DoneStatus task_play_frame(GenericAsyncTask *task, void *data); + + static AsyncTask::DoneStatus task_clear_text(GenericAsyncTask *task, void *data); + private: bool _is_open; bool _made_default_pipe; @@ -155,10 +167,11 @@ private: string _window_title; PT(GraphicsPipe) _default_pipe; - GraphicsEngine *_engine; + PT(GraphicsEngine) _engine; NodePath _data_root; EventHandler &_event_handler; + AsyncTaskManager &_task_mgr; typedef pvector< PT(WindowFramework) > Windows; Windows _windows; @@ -196,7 +209,6 @@ private: NodePath _help_text; NodePath _screenshot_text; - double _screenshot_clear_time; PT(RecorderController) _recorder; diff --git a/panda/src/framework/windowFramework.cxx b/panda/src/framework/windowFramework.cxx index 794aa11bca..30dc58e5fc 100644 --- a/panda/src/framework/windowFramework.cxx +++ b/panda/src/framework/windowFramework.cxx @@ -1302,7 +1302,7 @@ create_anim_controls() { setup_shuttle_button("4", 2, st_play_button); setup_shuttle_button(":", 3, st_forward_button); - _panda_framework->get_event_handler().add_hook("NewFrame", st_update_anim_controls, (void *)this); + _panda_framework->get_task_mgr().add(new GenericAsyncTask("controls", st_update_anim_controls, (void *)this)); } //////////////////////////////////////////////////////////////////// @@ -1442,12 +1442,13 @@ forward_button() { //////////////////////////////////////////////////////////////////// // Function: WindowFramework::st_update_anim_controls // Access: Private, Static -// Description: The static event handler function. +// Description: The static task function. //////////////////////////////////////////////////////////////////// -void WindowFramework:: -st_update_anim_controls(const Event *, void *data) { +AsyncTask::DoneStatus WindowFramework:: +st_update_anim_controls(GenericAsyncTask *, void *data) { WindowFramework *self = (WindowFramework *)data; self->update_anim_controls(); + return AsyncTask::DS_cont; } diff --git a/panda/src/framework/windowFramework.h b/panda/src/framework/windowFramework.h index d0cab782c5..a0d695c8f5 100644 --- a/panda/src/framework/windowFramework.h +++ b/panda/src/framework/windowFramework.h @@ -32,6 +32,7 @@ #include "pgSliderBar.h" #include "textNode.h" #include "eventHandler.h" +#include "genericAsyncTask.h" class PandaFramework; class AmbientLight; @@ -146,7 +147,7 @@ private: void play_button(); void forward_button(); - static void st_update_anim_controls(const Event *, void *data); + static AsyncTask::DoneStatus st_update_anim_controls(GenericAsyncTask *task, void *data); static void st_back_button(const Event *, void *data); static void st_pause_button(const Event *, void *data);