Script.h

00001 /***************************************************************************
00002  *                                                                         *
00003  *   (c) Art Tevs, MPI Informatik Saarbruecken                             *
00004  *       mailto: <tevs@mpi-sb.mpg.de>                                      *
00005  *                                                                         *
00006  *   This program is free software; you can redistribute it and/or modify  *
00007  *   it under the terms of the GNU General Public License as published by  *
00008  *   the Free Software Foundation; either version 2 of the License, or     *
00009  *   (at your option) any later version.                                   *
00010  *                                                                         *
00011  ***************************************************************************/
00012 
00013 
00014 #ifndef _NR_SCRIPT_RESOURCE__H_
00015 #define _NR_SCRIPT_RESOURCE__H_
00016 
00017 
00018 //----------------------------------------------------------------------------------
00019 // Includes
00020 //----------------------------------------------------------------------------------
00021 #include "Prerequisities.h"
00022 #include "IScript.h"
00023 
00024 namespace nrEngine{
00025 
00026 
00027         //! Simple script object based on engine's simple script language
00028         /**
00029          * This is a simple script language object. We use this language as engine's
00030          * default one to load other more powerfull script languages. This languages
00031          * could be found in plugins.
00032          *
00033          * Also simple scripts can be used to setup some variables or to write config
00034          * files that will be used to setup the engine's environment. This config files
00035          * could also contains plugins loading and file system setup. So actually this
00036          * simple language is enough to write simple applications.
00037          *
00038          * The scripts have very simple syntax:
00039          *  - each line is a script command
00040          *  - the line is bypassed to the script engine (so commands must be registered or it will cause no effect)
00041          *  - one command per one frame (if not other specified)
00042          *  - commands can be bound to a certain time (execute command at this time)
00043          *  - time values are always relative to the start time of the script
00044          *  - nontimed commands are executed sequentially
00045          *  - timed commands are executed quasi parallel to the nontimed
00046          *  - if one script calls another one, so the new one runs in parallel
00047          *
00048          *
00049          * Example of such a script (I called this timeline scripts):
00050          *
00051          *  seq_command param1 // execute seq_command sequantially with param1 as first argument
00052          *  1.452 | cmd1 par1   // execute the command cmd1 with parameter par1 at the time 1.452s (after starting of the script)
00053          *  1.693 | run script/script2.tml // execute script script/script2.tml after the time reaches 1.693
00054          *
00055          * Scripts could include subscripts. Subscripts are defined between
00056          * {} - brackets. The string between this brackets is used as a scipts
00057          * as if it was used in an explicit file. So the string is parsed
00058          * as a script and runs also parallel to the parent script. For timed
00059          * and non-timed commands the same restrictions are used as in non-subscripts.
00060          * Subscripts could define new subscripts. Because scripts are running as task, 
00061          * we add a task dependency between parent script and subscript. So parent script 
00062          * depends on subscript. This means parent script can only step forward after
00063          * subscripts has done their steps.
00064          *
00065          * NOTE:
00066          *      - We represent each script as a task, so the scripts are running in parallel
00067          *      - This type of script can run stepwise which is default behaviour. Specify it in
00068          *              another way if you want to run the script completely in one frame.
00069          *
00070          * @see IScript
00071          * \ingroup script
00072         **/
00073         class _NRExport Script : public IScript{
00074                 public:
00075 
00076                         //! Allocate memory and initilize simple script
00077                         Script();
00078 
00079                         //! Deallocate memory and release used data
00080                         ~Script();
00081 
00082 
00083                         /**
00084                         * Load simple script language from a string.
00085                         * @copydoc IScript::loadFromString()
00086                         **/
00087                         Result loadFromString(const std::string& str);
00088 
00089                         /**
00090                          * Execute the script completely. So the script will be
00091                          * executed until it finishes. This function will lock the execution
00092                          * of the engine while the script is running.
00093                          *
00094                          * NOTE: Timed commands used in nrScript would not been executed
00095                          *              here. This is because of the time which will not be updated
00096                          *              while the script is running. Updating the time, means either to
00097                          *              update the clock or the kernel. This is not allowed by tasks,
00098                          *              it means tasks can not update them self only kernel can do this.
00099                          *
00100                          *              So if you call execute() so only sequential commands will be
00101                          *              executed!
00102                          *
00103                          * NOTE: Be carefull by using looped scripts. If there is a loop, so the
00104                          *              script will also be executed in loop mode, so if you do not stop it
00105                          *              somehow your application could not react anymore!!!
00106                          *              If the script is looped, so warnign will be printed in a log file!
00107                         **/
00108                         Result fullRun();
00109 
00110                         /**
00111                          * Set if this script should run stepwise or completely in
00112                          * one cycle. If you run the script stepwise, so each line
00113                          * of the script is executed in one kernel cycle. Also time commands
00114                          * are getting executed as soon, as according time is passed.
00115                          *
00116                          * If you run the script fully in one cycle, so look to fullRun()
00117                          **/
00118                         NR_FORCEINLINE void setRunStepwise(bool b) { bRunStepwise = b; }
00119 
00120                         /**
00121                          * Check whenever the script is running stepwise
00122                          **/
00123                         NR_FORCEINLINE bool isRunStepwise() const { return bRunStepwise; }
00124 
00125                 private:
00126 
00127                         //! Return true if pipeline is full
00128                         bool hasCommands();
00129 
00130                         //! Script was started
00131                         void onStartScript();
00132 
00133                         //! Derived from IScript
00134                         Result run();
00135 
00136                         //!  Parse the given string as nrScript language
00137                         Result parse(const std::string&);
00138 
00139                         //! Remove all comments and empty lines from the script
00140                         std::string cleanScript(const std::string&);
00141 
00142                         //! Parse subscripts and return non-sub-script back
00143                         std::string parseSubscripts(const std::string&);
00144 
00145                         //! Set certain parameter from the script
00146                         bool setParameter(const std::string& param, const std::vector<std::string>& args);
00147 
00148                         //! Reset the sequentiall command fifo
00149                         void resetCommandFifo();
00150 
00151                         //! Reset the timed command fifo
00152                         void resetTimedCommandFifo(bool firstReset = false);
00153 
00154                         //! Tokenize the given line into command and arguments
00155                         void tokenize(const std::string& line, std::string& cmd, std::vector<std::string>& args);
00156 
00157                         //! Reset the command lists (if return false, so the task is removed from kernel)
00158                         bool reset();
00159 
00160                         //! Script is valid
00161                         bool mValid;
00162 
00163                         //! Error in line
00164                         int32 mLastLine;
00165 
00166                         //! Subscripts which belongs to this one
00167                         std::vector<ResourcePtr<IScript> > mSubscripts;
00168 
00169                         //! Time script have to stop after this duration
00170                         float32 mRunningTimeLength;
00171 
00172                         //! Time when script started
00173                         float32 mStopTime;
00174 
00175                         //! Run teh script stepwise
00176                         bool bRunStepwise;
00177 
00178                         //! Each command has this type
00179                         typedef struct _cmd{
00180 
00181                                 //! Timestamp ( = 0 -> command is not timed
00182                                 float32 timestamp;
00183 
00184                                 //! estimated starting time based on the global clock time
00185                                 float32 estimatedStart;
00186 
00187                                 //! current time of the command
00188                                 float32 time;
00189 
00190                                 //! function name
00191                                 std::string cmd;
00192 
00193                                 //! arguments of the command
00194                                 std::vector<std::string> args;
00195 
00196                         } Command;
00197 
00198                         //! Here we store our timed commands
00199                         std::vector< Command > mTimedCommand;
00200 
00201                         //! Here we store our sequentiall commands
00202                         std::vector< Command > mCommand;
00203 
00204                         //! Store command queue of waiting command ids
00205                         std::list< int32 > mCommandFifo;
00206 
00207                         //! Store timed commands sorted by their time in the queue
00208                         std::list< int32 > mTimedCommandFifo;
00209 
00210                         //! Script looping modes
00211                         typedef enum _loopMode{
00212                                 NO_LOOP = 0,
00213                                 LOOP_COMMAND = 1 << 0,
00214                                 LOOP_TIMED_COMMAND = 1 << 1,
00215                                 LOOP = LOOP_COMMAND | LOOP_TIMED_COMMAND
00216                         } LoopMode;
00217 
00218                         //! Looping mode
00219                         int32 mLoop;
00220 
00221                         //! Current time of the script
00222                         float32 mTime;
00223                         
00224                         //! Does script run to the first time
00225                         bool mFirstRunTimed;
00226                         
00227                         //! Timer used by the script (usefull for timed commands)
00228                         SharedPtr<Timer> mTimer;
00229                         
00230                         //! Specified script starting time (ala absolute time start)
00231                         float32 mScriptStartTime;
00232                         
00233                         //! Run only one step from the script
00234                         Result step();
00235 
00236         };
00237 
00238 
00239 };
00240 
00241 #endif

Generated on Wed Sep 12 23:19:42 2007 for nrEngine by  doxygen 1.5.1