//Returns 0 if the call terminated. If the caller provides a callback and the thread does not terminate,
//it will continue to run. Otherwise it will be killed. Returns 1 in this case.
int CCobInstance::RealCall(int functionId, vector<int> &args, CBCobThreadFinish cb, void *p1, void *p2)
{
	CCobThread *t = new CCobThread(script, this);
	t->Start(functionId, args, false);

#if COB_DEBUG > 0
	if (COB_DEBUG_FILTER)
		logOutput.Print("Calling %s:%s", script.name.c_str(), script.scriptNames[functionId].c_str());
#endif

	int res = t->Tick(30);
	t->CommitAnims(30);

	//Make sure this is run even if the call terminates instantly
	if (cb) 
		t->SetCallback(cb, p1, p2);

	if (res == -1) {
		//Retrieve parameter values from stack		
		for (unsigned int i = 0; i < args.size(); ++i) {
			args[i] = t->GetStackVal(i);
		}
		delete t;
		return 0;
	}
	else {
		//It has already added itself to the correct scheduler (global for sleep, or local for anim)
		return 1;
	}
}
示例#2
0
/**
 * @brief Calls a cob script function
 * @param functionId int cob script function id
 * @param args vector<int> function arguments
 * @param cb CBCobThreadFinish Callback function
 * @param p1 void* callback argument #1
 * @param p2 void* callback argument #2
 * @return 0 if the call terminated. If the caller provides a callback and the thread does not terminate,
 *  it will continue to run. Otherwise it will be killed. Returns 1 in this case.
 */
int CCobInstance::RealCall(int functionId, vector<int> &args, CBCobThreadFinish cb, void *p1, void *p2)
{
	if (functionId < 0 || size_t(functionId) >= script.scriptNames.size()) {
		if (cb) {
			// in case the function doesnt exist the callback should still be called
			(*cb)(0, p1, p2);
		}
		return -1;
	}

	CCobThread *t = new CCobThread(script, this);
	t->Start(functionId, args, false);

#if COB_DEBUG > 0
	if (COB_DEBUG_FILTER)
		logOutput.Print("Calling %s:%s", script.name.c_str(), script.scriptNames[functionId].c_str());
#endif

	int res = t->Tick(30);
	t->CommitAnims(30);

	// Make sure this is run even if the call terminates instantly
	if (cb)
		t->SetCallback(cb, p1, p2);

	if (res == -1) {
		unsigned int i = 0, argc = t->CheckStack(args.size());
		// Retrieve parameter values from stack
		for (; i < argc; ++i)
			args[i] = t->GetStackVal(i);
		// Set erroneous parameters to 0
		for (; i < args.size(); ++i)
			args[i] = 0;
		delete t;
		return 0;
	}
	else {
		// It has already added itself to the correct scheduler (global for sleep, or local for anim)
		return 1;
	}
}
void CCobEngine::Tick(int deltaTime)
{
START_TIME_PROFILE

	GCurrentTime += deltaTime;

#if COB_DEBUG > 0
	logOutput.Print("----");
#endif

	//Advance all running threads
	for (list<CCobThread *>::iterator i = running.begin(); i != running.end(); ++i) {
		//logOutput.Print("Now 1running %d: %s", GCurrentTime, (*i)->GetName().c_str());
#ifdef _CONSOLE
		printf("----\n");
#endif
		int res = (*i)->Tick(deltaTime);
		(*i)->CommitAnims(deltaTime);

		if (res == -1) {
			delete *i;
		}
	}

	//A thread can never go from running->running, so clear the list
	//note: if preemption was to be added, this would no longer hold
	//however, ta scripts can not run preemptively anyway since there isn't any synchronization methods available
	running.clear();

	//The threads that just ran may have added new threads that should run next tick
	for (list<CCobThread *>::iterator i = wantToRun.begin(); i != wantToRun.end(); ++i) {
		running.push_front(*i);
	}
	wantToRun.clear();

	//Check on the sleeping threads
	if (sleeping.size() > 0) {
		CCobThread *cur = sleeping.top();
		while ((cur != NULL) && (cur->GetWakeTime() < GCurrentTime)) {	

			// Start with removing the executing thread from the queue
			sleeping.pop();

			//Run forward again. This can quite possibly readd the thread to the sleeping array again
			//But it will not interfere since it is guaranteed to sleep > 0 ms
			//logOutput.Print("Now 2running %d: %s", GCurrentTime, cur->GetName().c_str());
#ifdef _CONSOLE
			printf("+++\n");
#endif
			if (cur->state == CCobThread::Sleep) {
				cur->state = CCobThread::Run;
				int res = cur->Tick(deltaTime);
				cur->CommitAnims(deltaTime);
				if (res == -1)
					delete cur;
			} else if (cur->state == CCobThread::Dead) {
				delete cur;
			} else {
				logOutput.Print("CobError: Sleeping thread strange state %d", cur->state);
			}
			if (sleeping.size() > 0) 
				cur = sleeping.top();
			else
				cur = NULL;
		}
	}

	//Tick all instances that have registered themselves as animating
	list<CCobInstance *>::iterator it = animating.begin();
	list<CCobInstance *>::iterator curit;
	while (it != animating.end()) {			
		curit = it++;		
		if ((*curit)->Tick(deltaTime) == -1)
			animating.erase(curit);		
	}
END_TIME_PROFILE("Scripts");
}