//-------------------------------------------------------------------- void IThread::threadStart() { // Check if we have already a thread created if (mThread) { NR_Log(Log::LOG_KERNEL, Log::LL_WARNING, "IThread: the appropriate thread is already running!"); return; } NR_Log(Log::LOG_KERNEL, "IThread: Create thread and start it"); mThread.reset(new boost::thread(boost::bind(&IThread::run, this))); // initialise the attribute /*pthread_attr_init(&mThreadAttr); // create the joinable attribute for thsi thread pthread_attr_setdetachstate(&mThreadAttr, PTHREAD_CREATE_JOINABLE); // setup thread scheduling attribute pthread_attr_setschedpolicy(&mThreadAttr, SCHED_RR); // now create a thread and let it run int res = pthread_create(&mThread, &mThreadAttr, IThread::run, (void *)this); if (res){ NR_Log(Log::LOG_KERNEL, Log::LL_ERROR, "IThread: creation of a thread failed with error code %d", res); return; }*/ mThreadState = THREAD_RUNNING; mThreadState = THREAD_RUNNING; mThread.reset(new boost::thread(boost::bind(IThread::run, this))); }
//------------------------------------------------------------------------ Result EventManager::emit(const std::string& name, SharedPtr<Event> event) { // Profiling of the engine _nrEngineProfile("EventManager.emit"); // if user want to send the message to all channels if (name.length() == 0){ NR_Log(Log::LOG_ENGINE, Log::LL_CHATTY, "EventManager: Emit event '%s' to all channels", event->getEventType()); ChannelDatabase::iterator it = mChannelDb.begin(); for (; it != mChannelDb.end(); it++) it->second->push(event); }else{ NR_Log(Log::LOG_ENGINE, Log::LL_CHATTY, "EventManager: Emit event '%s' to '%s'", event->getEventType(), name.c_str()); // get the channel according to the name and emit the message SharedPtr<EventChannel> channel = getChannel(name); if (channel == NULL) return EVENT_CHANNEL_NOT_EXISTS; channel->push(event); } // ok return OK; }
//------------------------------------------------------------------------ Result EventManager::registerFactory(const std::string& name, SharedPtr<EventFactory> factory) { // get a factory by name FactoryDatabase::iterator it = mFactoryDb.find(name); if (it != mFactoryDb.end()){ NR_Log(Log::LOG_ENGINE, Log::LL_WARNING, "EventManager: The event factory %s is already registered", name.c_str()); return EVENT_FACTORY_FOUND; } NR_Log(Log::LOG_ENGINE, Log::LL_NORMAL, "EventManager: Register event factory %s", name.c_str()); mFactoryDb[name] = factory; return OK; }
//------------------------------------------------------------------------ bool Engine::initializeEngine() { // give some info about the underlying engine NR_Log(Log::LOG_ENGINE | Log::LOG_CONSOLE | Log::LOG_KERNEL, (char*)"nrEngine v%s - %s", convertVersionToString(nrEngineVersion).c_str(), NR_VERSION_NAME); // initialize the clock SharedPtr<TimeSource> timeSource(new TimeSource()); // initialize profiler singleton _profiler = (new Profiler(timeSource)); if (_profiler == NULL) NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, (char*)"Profiler singleton could not be created. Probably memory is full"); // now add the clock into kernel _clock->setTimeSource(timeSource); _clock->setTaskType(TASK_SYSTEM); _kernel->AddTask(SharedPtr<ITask>(_clock, null_deleter()), ORDER_SYS_FIRST); // initialize resource manager singleton _event = (new EventManager()); if (_event == NULL) NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, (char*)"Event manager singleton could not be created. Probably memory is full"); _event->createChannel(NR_DEFAULT_EVENT_CHANNEL); _event->setTaskType(TASK_SYSTEM); _kernel->AddTask(SharedPtr<ITask>(_event, null_deleter()), ORDER_SYS_SECOND); // initialise default scripting methods DefaultScriptingFunctions::addMethods(); // initialize resource manager singleton _resmgr = (new ResourceManager()); if (_resmgr == NULL) NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, (char*)"Resource manager singleton could not be created. Probably memory is full"); // Add the file reading functionality ResourceLoader fileLoader (new FileStreamLoader()); _resmgr->registerLoader((char*)"FileStreamLoader", fileLoader); // create an instance of plugin loader and add it to the resource manager ResourceLoader loader ( new PluginLoader() ); _resmgr->registerLoader((char*)"PluginLoader", loader); // create simple scripting language instancies ResourceLoader scriptLoader( new ScriptLoader() ); _resmgr->registerLoader((char*)"ScriptLoader", scriptLoader); return true; }
//------------------------------------------------------------------------ Result EventManager::removeFactory(const std::string& name) { // check if the the factory list is not empty if (mFactoryDb.size() == 0) return OK; // get a factory by name FactoryDatabase::iterator it = mFactoryDb.find(name); if (it == mFactoryDb.end()){ NR_Log(Log::LOG_ENGINE, Log::LL_WARNING, "EventManager: The event factory %s was not found", name.c_str()); return EVENT_FACTORY_NOT_FOUND; } NR_Log(Log::LOG_ENGINE, Log::LL_NORMAL, "EventManager: Remove event factory %s", name.c_str()); mFactoryDb.erase(it); return OK; }
//---------------------------------------------------------------------- nr3D::nr3D() { // initialize default variables mName = "nr3D-Package"; mFullName = "3D-Engine package for nrEngine"; NR_Log(Log::LOG_PLUGIN, "%s: %s",mName.c_str(), mFullName.c_str()); // check whenever engine is valid if (!Engine::valid()) { NR_Log(Log::LOG_PLUGIN, Log::LL_ERROR, "%s: Engine must be initialized before!", mName.c_str()); NR_EXCEPT(ENGINE_ERROR, "Engine must be initialized before creating a nr3D", "nr3D::nr3D()"); } // initialize glfw task }
//---------------------------------------------------------------------------------- Result Plugin::unloadResource() { // only unload, if we are loaded if (isResourceLoaded()) { // call the release function of the plugin m_plgRelease(); // set all symbols to NULL m_plgInitialize = NULL; m_plgEngineVersion = NULL; m_plgVersionString = NULL; m_plgError = NULL; m_plgRelease = NULL; // now unload the plugin handle from memory if (NR_PLUGIN_UNLOAD(mPluginHandle)) { NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, "Could not unload plugin %s. System Msg: %s", getResourceName().c_str(), getLastPluginError().c_str()); return PLG_UNLOAD_ERROR; } // set the handle to 0 mPluginHandle = NULL; markResourceUnloaded(); } // OK return OK; }
//------------------------------------------------------------------------ EventManager::EventManager(){ setTaskName("EventSystem"); NR_Log(Log::LOG_ENGINE, "EventManager: Initialize the event management system"); // create default system wide channel createChannel(NR_DEFAULT_EVENT_CHANNEL); }
//---------------------------------------------------------------------------------- size_t FileStream::readDelim(void* buf, size_t count, const ::std::string& delim) { if (!mStream) return 0; if (delim.empty()){ NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, "FileStream::readDelim(): No delimiter provided"); return 0; } if (delim.size() > 1){ NR_Log(Log::LOG_ENGINE, Log::LL_WARNING, "FileStream::readDelim(): Only first character of delimiter \"%s\" is used", delim.c_str()); } // Deal with both Unix & Windows LFs bool trimCR = false; if (delim.at(0) == '\n'){ trimCR = true; } // maxCount + 1 since count excludes terminator in getline mStream->getline(static_cast<char*>(buf), count+1, delim.at(0)); size_t ret = mStream->gcount(); if (mStream->fail()){ // Did we fail because of maxCount hit? if (ret == count){ // clear failbit for next time mStream->clear(); }else{ NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, "FileStream::readDelim(): Error during reading the stream"); } } if (!ret){ (static_cast<char*>(buf))[1] = '\0'; }else{ // trim off CR if we found CR/LF if (trimCR && (static_cast<char*>(buf))[ret] == '\r'){ --ret; (static_cast<char*>(buf))[ret+1] = '\0'; } } return ret; }
//-------------------------------------------------------------------- void Profiler::logResults(Log::LogTarget lt){ // if the profiler is enabled if (!mEnabled) return; // sort the history so we get profiles that need more time on the top mProfileHistory.sort(); ProfileHistoryList::iterator iter; NR_Log(lt, "--------------------------------------Profiler Results------------------------------"); NR_Log(lt, "| Name | Avg(\%) | Max(\%) | Min(\%) | Time sec | Calls |"); NR_Log(lt, "------------------------------------------------------------------------------------"); // log system results NR_Log(lt, "| System Profiles |"); for (iter = mProfileHistory.begin(); iter != mProfileHistory.end(); iter++) { // only for system profiles if (iter->isSystemProfile){ // create an indent that represents the hierarchical order of the profile std::string indent = " "; //for (uint32 i = 0; i < (*iter).hierarchicalLvl; i++) // indent = indent + " --"; indent += (*iter).name; indent.resize(27, ' '); logLine(indent.c_str(), iter->minTime, iter->maxTime, iter->realTime, iter->totalTime, iter->totalCalls); } } // log application results NR_Log(lt, "|----------------------------------------------------------------------------------|"); NR_Log(lt, "| Application Profiles |"); for (iter = mProfileHistory.begin(); iter != mProfileHistory.end(); iter++) { // only for application profiles if (!iter->isSystemProfile){ // create an indent that represents the hierarchical order of the profile std::string indent = " "; //for (uint32 i = 0; i < (*iter).hierarchicalLvl; i++) // indent = indent + " --"; indent += (*iter).name; indent.resize(27, ' '); logLine(indent.c_str(), iter->minTime, iter->maxTime, iter->realTime, iter->totalTime, iter->totalCalls); } } NR_Log(lt, "| |"); NR_Log(lt, "------------------------------------------------------------------------------------"); }
//------------------------------------------------------------------------ bool Engine::loadPlugin(const std::string& path, const std::string& file, const std::string& name) { // check if the engine is initialized if (_resmgr == NULL) { NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, (char*)"Engine was not initialized properly"); return false; } // try to load the resource and check for the error code IResourcePtr plg = _resmgr->loadResource(name, (char*)"Plugins", path + file, (char*)"Plugin"); return true; }
//---------------------------------------------------------------------------------- Property& PropertyList::operator[](const std::string& name) { // search for the key for (iterator it = begin(); it != end(); it++) if (it->getName() == name) return *it; // we could not find it, so create it and return reference Property p(name); push_back(p); // some debug info NR_Log(Log::LOG_ENGINE, Log::LL_DEBUG, "Property: Initialize new property '%s'", name.c_str()); return back(); }
//------------------------------------------------------------------------ Result EventManager::createChannel(const std::string& name) { // check first whenever such a channel is already in the database if (getChannel(name)) return EVENT_CHANNEL_EXISTS; // channel is not in the database, so create it and fill it's data SharedPtr<EventChannel> channel(new EventChannel(this, name)); // push the channel into the database mChannelDb[name] = channel; NR_Log(Log::LOG_ENGINE, "EventManager: New channel \"%s\" created", name.c_str()); // OK return OK; }
//------------------------------------------------------------------------ Result EventChannel::add(EventActor* actor, bool notice) { // check if actor has got a name if (actor == NULL) return OK; if (actor->getName().length() == 0) { NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, "EventChannel (%s): Want to connect nameless actor", getName().c_str()); return EVENT_NO_VALID_ACTOR; } // we first check whenever the actor is already connected if (isConnected(actor->getName())) return EVENT_ALREADY_CONNECTED; // connect the actor to the OnEvent - Signal slot mActorDb[actor->getName()] = actor; // notice an actor that he is got a connection now if (notice) actor->_noticeConnected(this); // Log debug stuff NR_Log(Log::LOG_ENGINE, Log::LL_DEBUG, "EventChannel (%s): New actor connected \"%s\"", getName().c_str(), actor->getName().c_str()); return OK; }
//-------------------------------------------------------------------- void IThread::run(void* _mythread) { // try to cast the given parameter to IThread pointer IThread* mythread = static_cast<IThread*>(_mythread); if (mythread == NULL) { NR_Log(Log::LOG_KERNEL, Log::LL_ERROR, "IThread: not valid parameter was specified for IThread::run(void*) method"); return; } // now loop the thread until some messages occurs bool run = true; while (run){ // kernel requested to suspend the thread if (mythread->mThreadState == THREAD_NEXT_SUSPEND) { // notice about suspending and go into sleep mode mythread->changeState(THREAD_SLEEPING); mythread->_noticeSuspend(); // kernel requested to resume the execution }else if (mythread->mThreadState == THREAD_NEXT_RESUME) { // notice about resuming the work and start it again mythread->changeState(THREAD_RUNNING); mythread->_noticeResume(); // kernel does not requested anything, so run the task }else if (mythread->mThreadState == THREAD_RUNNING) { mythread->_noticeUpdate(); } // check for the stop message, then stop the thread // this is a reading mutex, so do not have to lock it run = mythread->mThreadState != THREAD_STOP; // we now yield the used timeslice for another threads yield(mythread); } // notice to stop the underlying task mythread->_noticeStop(); // exit the thread //return NULL; }
//------------------------------------------------------------------------ void EventChannel::_disconnectAll() { // Profiling of the engine _nrEngineProfile("EventChannel._disconnectAll"); // some logging NR_Log(Log::LOG_ENGINE, Log::LL_DEBUG, "EventChannel (%s): Disconnect all actors", getName().c_str()); // iterate through all connections and close them ActorDatabase::iterator it = mActorDb.begin(); for (; it != mActorDb.end(); it++){ mActorDb.erase(it); it->second->_noticeDisconnected(this); } }
//------------------------------------------------------------------------ Result EventChannel::del(EventActor* actor, bool notice) { // we first check whenever the actor is already connected if (!isConnected(actor->getName())) return EVENT_NOT_CONNECTED; // disconnect the actor to the OnEvent - Signal slot mActorDb.erase(mActorDb.find(actor->getName())); // notice an actor that it is disconnected now if (notice) actor->_noticeDisconnected(this); // Log debug stuff NR_Log(Log::LOG_ENGINE, Log::LL_DEBUG, "EventChannel (%s): Actor \"%s\" disconnected ", getName().c_str(), actor->getName().c_str()); return OK; }
//------------------------------------------------------------------------ Result EventChannel::add(EventActor* actor, bool notice) { // we first check whenever the actor is already connected if (isConnected(actor->getName())) return EVENT_ALREADY_CONNECTED; // connect the actor to the OnEvent - Signal slot mActorDb[actor->getName()] = actor; // notice an actor that he is got a connection now if (notice) actor->_noticeConnected(this); // Log debug stuff NR_Log(Log::LOG_ENGINE, Log::LL_DEBUG, "EventChannel (%s): New actor connected \"%s\"", getName().c_str(), actor->getName().c_str()); return OK; }
//------------------------------------------------------------------------ Result EventManager::removeChannel(const std::string& name) { // check first whenever such a channel is already in the database SharedPtr<EventChannel> channel = getChannel(name); if (!channel) return EVENT_CHANNEL_NOT_EXISTS; // disconnect all the actor from the channel channel->_disconnectAll(); mChannelDb.erase(mChannelDb.find(name)); // log info NR_Log(Log::LOG_ENGINE, "EventManager: Remove channel \"%s\"", name.c_str()); // OK return OK; }
//---------------------------------------------------------------------------------- Property& PropertyManager::getPropertyByFullname(const std::string& fullname) { // iterate through all groups PropertyMap::iterator it = mPropertyMap.begin(); for (; it != mPropertyMap.end(); it++) { // search for such an element PropertyList::iterator jt = it->second.begin(); for (; jt != it->second.end(); jt++) if (jt->getFullname() == fullname) { return *jt; } } // we have not found any such element, so create one NR_Log(Log::LOG_ENGINE, Log::LL_WARNING, "PropertyManager: Property with fullname '%s' is not registered, so create it in default group", fullname.c_str()); return getProperty(fullname, "."); }
//---------------------------------------------------------------------------------- Result FileStream::open (const ::std::string& fileName) { // create a pointer to the stream object and open the file mStream.reset (new ::std::ifstream(fileName.c_str())); // check if the file could be found if (!mStream->good()) { NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, "The file \"%s\" was not found", fileName.c_str()); return FILE_NOT_FOUND; } mResFileName = fileName; // calculate the size mStream->seekg(0, ::std::ios_base::end); mSize = mStream->tellg(); mStream->seekg(0, ::std::ios_base::beg); return OK; }
//------------------------------------------------------------------------ SharedPtr<Timer> Clock::createTimer(){ // create timer as observer SharedPtr<ITimeObserver> timer( new Timer(Clock::GetSingleton()), null_deleter()); // add him to the list int32 id = addObserver(timer); if (id == 0){ NR_Log(Log::LOG_ENGINE, Log::LL_WARNING, "Clock::createTimer(): Can not add timer to the observer list"); } // set the id of the timer timer->_observerID = id; // return created timer return ::boost::dynamic_pointer_cast<Timer, ITimeObserver>(timer); }
//---------------------------------------------------------------------------------- Property& PropertyManager::getProperty(const std::string& name, const std::string& group) { // get list which should contain the property PropertyList& list = mPropertyMap[group]; // check if such a property exists in the database PropertyList::iterator it = list.begin(); for (; it != list.end(); it++) if (it->getName() == name) return *it; // we haven't found this property hence generate new one Property p; p.mName = name; p.mFullname = group + std::string(".") + name; // some debug info NR_Log(Log::LOG_ENGINE, Log::LL_DEBUG, "Property: Initialize new property '%s.%s'", group.c_str(), name.c_str()); // add property into the list and return the reference list.push_back(p); return list.back(); }
//----------------------------------------------------------------------- void Profiler::logLine(const char* name, float32 min, float32 max, float32 frameTime, float32 totalTime, uint32 totalCalls) { // create some strings containing the statistics char avg[32]; sprintf(avg, "%2.2f", (totalTime / totalCalls) * 100.0f); char smin[32]; sprintf(smin, "%2.2f", min * 100.0f); char smax[32]; sprintf(smax, "%2.2f", max * 100.0f); char tim[32]; sprintf(tim, "%4.6f", frameTime); char cls[32]; sprintf(cls, "%d", totalCalls); char ttm[32]; sprintf(ttm, "%4.6f", totalTime); NR_Log(Log::LOG_APP, "| %s | %-6s| %-6s| %-6s| %-13s| %-9s|", name, avg, smax, smin, tim, cls); }
//---------------------------------------------------------------------------------- Result Plugin::reloadResource(PropertyList* params) { if (!isResourceLoaded()) { // get filename const std::string& name = getResourceFilenameList().front(); // now load the library mPluginHandle = (PluginHandle)NR_PLUGIN_LOAD(name.c_str()); // check whenever the library could be loaded if (mPluginHandle == NULL) { NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, "Plugin %s could not be loaded! System Msg: %s", getResourceName().c_str(), getLastPluginError().c_str()); return PLG_COULD_NOT_LOAD; } // force the plugin resource object to initialize itself after loading return initialize(params); } return OK; }
//---------------------------------------------------------------------------------- Result Plugin::initialize(PropertyList* params) { NR_Log(Log::LOG_ENGINE, Log::LL_DEBUG, "Check if the loaded library is valid plugin"); // get version information m_plgEngineVersion = (plgEngineVersion)getSymbol("plgEngineVersion"); m_plgVersionString = (plgVersionString)getSymbol("plgVersionString"); if (!m_plgEngineVersion || !m_plgVersionString) { NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, "Plugin seems not to be written for the nrEngine"); NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, "plgVersionString/plgEngineVersion symbols were not found!!!"); return PLG_SYMBOL_NOT_FOUND; } // Log this NR_Log(Log::LOG_ENGINE, "Plugin found: %s written for nrEngine v%s", m_plgVersionString(), convertVersionToString(m_plgEngineVersion()).c_str()); // check if plugin is working with the current engine version if (m_plgEngineVersion() > nrEngineVersion){ NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, "Plugin has got greater version as the engine, so plugin not loaded"); return PLG_WRONG_VERSION; } // log something NR_Log(Log::LOG_PLUGIN, "Initialize plugin %s", getResourceName().c_str()); #define GET_SYMBOL(var, type)\ {\ NR_Log(Log::LOG_ENGINE, Log::LL_DEBUG, "Get plugin symbol %s", #type);\ var = (type)getSymbol(#type);\ if (!var){\ NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, "Plugin symbol %s was not found", #type);\ return PLG_SYMBOL_NOT_FOUND;\ }\ } // Get plugin symbols GET_SYMBOL(m_plgInitialize, plgInitialize); GET_SYMBOL(m_plgError, plgError); GET_SYMBOL(m_plgRelease, plgRelease); #undef GET_SYMBOL // call the function and check for return code int result = m_plgInitialize(Engine::instance(), params); // check for error if (result != 0){ NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, "Plugin returns error %d (%s). See plugin log for more detail information", result, m_plgError(result)); return PLG_EXTERNAL_ERROR; } // now get some extra symbols /*m_plgGetMethods = (plgGetMethods)getSymbol("plgGetMethods"); m_plgCall = (plgCall)getSymbol("plgCall"); if (m_plgGetMethods){ // get the list of methods provided by this plugin m_plgGetMethods(mPlgMethods); NR_Log(Log::LOG_ENGINE, Log::LL_DEBUG, "Plugin provides following symbols: "); // now go through each of this method and print some log info about it for (uint32 i=0; i < mPlgMethods.size(); i++){ std::string params; for (uint32 j=0; j < mPlgMethods[i].param.size(); j++){ params += mPlgMethods[i].param[j].name; if (j < mPlgMethods[i].param.size() - 1) params += ", "; } NR_Log(Log::LOG_ENGINE, Log::LL_DEBUG, " found - %s (%s)", mPlgMethods[i].name.c_str(), params.c_str()); } }*/ // all right! return OK; }