Exemple #1
0
static bool FnLayerSetPixel(C4PropList * _this, int32_t x, int32_t y, const C4Value& fg_value_c4v, const C4Value& bg_value_c4v)
{
	// Layer script function: Set pixel at position x,y to to_value in _this layer
	C4MapScriptLayer *layer = _this->GetMapScriptLayer();
	if (!layer) return false;
	uint8_t fg, bg;

	if (fg_value_c4v.GetType() == C4V_Nil)
	{
		fg = layer->GetPix(x,y,0);
	}
	else
	{
		const C4Value& val = fg_value_c4v;
		C4String *str = val.getStr();
		if (str != NULL)
		{
			if (!TexColSingle(str->GetCStr(), fg))
				throw C4AulExecError("MapLayer::SetPixel: Trying to set invalid pixel value.");
		}
		else
		{
			if (!Inside(val.getInt(), 0, 255))
				throw C4AulExecError("MapLayer::SetPixel: Trying to set invalid pixel value.");
			fg = val.getInt();
		}
	}

	if (bg_value_c4v.GetType() == C4V_Nil)
	{
		bg = layer->GetBackPix(x,y,0);
	}
	else
	{
		const C4Value& val = bg_value_c4v;
		C4String *str = val.getStr();
		if (str != NULL)
		{
			if (!TexColSingle(str->GetCStr(), bg))
				throw C4AulExecError("MapLayer::SetPixel: Trying to set invalid pixel value.");
		}
		else
		{
			if (!Inside(val.getInt(), 0, 255))
				throw C4AulExecError("MapLayer::SetPixel: Trying to set invalid pixel value.");
			bg = val.getInt();
		}
	}
			
	return layer->SetPix(x,y,fg,bg);
}
void C4ParticleValueProvider::SetParameterValue(int type, const C4Value &value, float C4ParticleValueProvider::*floatVal, int C4ParticleValueProvider::*intVal, size_t keyFrameIndex)
{
	// just an atomic data type
	if (value.GetType() == C4V_Int)
	{
		if (type == VAL_TYPE_FLOAT)
			this->*floatVal = (float)value.getInt();
		else if (type == VAL_TYPE_INT)
			this->*intVal = value.getInt();
		else if (type == VAL_TYPE_KEYFRAMES)
			this->keyFrames[keyFrameIndex] = (float)value.getInt();
	}
	else if (value.GetType() == C4V_Array)
	{
		//  might be another value provider!
		C4ParticleValueProvider *child = new C4ParticleValueProvider();
		childrenValueProviders.push_back(child);

		child->Set(*value.getArray());
		child->typeOfValueToChange = type;

		if (type == VAL_TYPE_FLOAT)
		{
			child->floatValueToChange = floatVal;
		}
		else if (type == VAL_TYPE_INT)
		{
			child->intValueToChange = intVal;
		}
		else if (type == VAL_TYPE_KEYFRAMES)
		{
			child->keyFrameIndex = keyFrameIndex;
		}

	}
	else // invalid
	{
		if (type == VAL_TYPE_FLOAT)
			this->*floatVal = 0.f;
		else if (type == VAL_TYPE_INT)
			this->*intVal = 0;
		else if (type == VAL_TYPE_KEYFRAMES)
			this->keyFrames[keyFrameIndex] = 0.f;
	}
}
void C4ValueArray::SetSlice(int32_t startIndex, int32_t endIndex, const C4Value &Val)
{
    // maximum bounds
    if(startIndex >= MaxSize) throw C4AulExecError("array slice: start index exceeds maximum capacity");

    // index from back
    if(startIndex < 0) startIndex += iSize;
    if(endIndex < 0) endIndex += iSize;

    // ensure relevant bounds
    if(startIndex < 0) throw C4AulExecError("array slice: start index out of range");
    if(endIndex < 0) throw C4AulExecError("array slice: end index out of range");
    if(endIndex < startIndex)
        endIndex = startIndex;

    // setting an array?
    if(Val.GetType() == C4V_Array)
    {
        const C4ValueArray &Other = *Val._getArray(); // Remember that &Other could be equal to this, carefull with modifying pData

        // Calculcate new size
        int32_t iNewEnd = std::min(startIndex + Other.GetSize(), (int32_t)MaxSize);
        int32_t iNewSize = iNewEnd;
        if(endIndex < iSize)
            iNewSize += iSize - endIndex;
        iNewSize = std::min(iNewSize, (int32_t)MaxSize);
        int32_t iOtherSize = Other.GetSize();

        if(iNewSize != iSize)
        {
            int32_t i,j;
            C4Value* pnData = pData;

            if(iNewSize > iCapacity)
            {
                pnData = new C4Value [iNewSize];

                // Copy first part of old array
                for(i = 0; i < startIndex && i < iSize; ++i)
                    pnData[i] = pData[i];
            }

            // Copy the second slice of the new array
            for(i = iNewEnd, j = endIndex; i < iNewSize; ++i, ++j)
            {
                assert(j < iSize);
                pnData[i] = pData[j];
            }

            // Copy the data
            // Since pnData and pData can be the same, we can not copy with
            //for(i = startIndex, j = 0; i < iNewEnd; ++i, ++j)
            // but have to start from the end of the copied sequence. That works, since j <= i
            for(i = iNewEnd - 1, j = iNewEnd - startIndex - 1; i >= startIndex; --i, --j)
            {
                assert(j < iOtherSize);
                pnData[i] = Other.pData[j];
            }

            // Other values should have been initialized to 0 by new
            if(pData != pnData)
            {
                delete [] pData;
                pData = pnData;
                iCapacity = iSize = iNewSize;
            }
            else
            {
                // "ignore" the now unused part
                for(i = iNewSize; i < iSize; ++i)
                    pData[i].Set0();
                iSize = iNewSize;
            }

        } else // slice has the same size as inserted array
            // Copy the data. changing pData does not break because if &Other == this and iNewSize == iSize, nothing happens at all
            for(int32_t i = startIndex, j = 0; j < iOtherSize; i++, j++)
                pData[i] = Other.pData[j];

    } else { /* if(Val.GetType() != C4V_Array) */
        if(endIndex > MaxSize) endIndex = iSize;

        // Need resize?
        if(endIndex > iSize) SetSize(endIndex);

        // Fill
        for(int32_t i = startIndex; i < endIndex; i++)
            pData[i] = Val;

    }

}
C4AulDebug::ProcessLineResult C4AulDebug::ProcessLine(const StdStrBuf &Line)
{
	// Get command
	StdStrBuf Cmd;
	Cmd.CopyUntil(Line.getData(), ' ');
	// Get data
	const char *szData = Line.getPtr(Cmd.getLength());
	if (*szData) szData++;
	// Identify command
	const char *szCmd = Cmd.getData();
	if (SEqualNoCase(szCmd, "HELP"))
		return ProcessLineResult(false, "Yeah, like I'm going to explain that /here/");
	else if (SEqualNoCase(szCmd, "BYE") || SEqualNoCase(szCmd, "QUIT"))
		C4NetIOTCP::Close(PeerAddr);
	else if (SEqualNoCase(szCmd, "SAY"))
		::Control.DoInput(CID_Message, new C4ControlMessage(C4CMT_Normal, szData), CDT_Direct);
	else if (SEqualNoCase(szCmd, "CMD"))
		::MessageInput.ProcessCommand(szData);
	else if (SEqualNoCase(szCmd, "STP") || SEqualNoCase(szCmd, "S"))
		eState = DS_Step;
	else if (SEqualNoCase(szCmd, "GO") || SEqualNoCase(szCmd, "G"))
		eState = DS_Go;
	else if (SEqualNoCase(szCmd, "STO") || SEqualNoCase(szCmd, "O"))
		eState = DS_StepOver;
	else if (SEqualNoCase(szCmd, "STR") || SEqualNoCase(szCmd, "R"))
		eState = DS_StepOut;
	else if (SEqualNoCase(szCmd, "EXC") || SEqualNoCase(szCmd, "E"))
	{
		C4AulScriptContext* context = pExec->GetContext(pExec->GetContextDepth()-1);
		int32_t objectNum = C4ControlScript::SCOPE_Global;
		if (context && context->Obj && context->Obj->GetObject())
			objectNum = context->Obj->GetObject()->Number;
		::Control.DoInput(CID_Script, new C4ControlScript(szData, objectNum, true), CDT_Decide);
	}
	else if (SEqualNoCase(szCmd, "PSE"))
		if (Game.IsPaused())
		{
			Game.Unpause();
			return ProcessLineResult(true, "Game unpaused.");
		}
		else
		{
			Game.Pause();
			return ProcessLineResult(true, "Game paused.");
		}
	else if (SEqualNoCase(szCmd, "LST"))
	{
		for (C4AulScript* script = ScriptEngine.Child0; script; script = script->Next)
		{
			SendLine(RelativePath(script->ScriptName));
		}
	}

	// toggle breakpoint
	else if (SEqualNoCase(szCmd, "TBR"))
	{
		using namespace std;
		// FIXME: this doesn't find functions which were included/appended
		string scriptPath = szData;
		size_t colonPos = scriptPath.find(':');
		if (colonPos == string::npos)
			return ProcessLineResult(false, "Missing line in breakpoint request");
		int line = atoi(&scriptPath[colonPos+1]);
		scriptPath.erase(colonPos);

		C4AulScript *script;
		for (script = ScriptEngine.Child0; script; script = script->Next)
		{
			if (SEqualNoCase(RelativePath(script->ScriptName), scriptPath.c_str()))
				break;
		}

		auto sh = script ? script->GetScriptHost() : NULL;
		if (sh)
		{
			C4AulBCC * found = NULL;
			for (auto script = ::ScriptEngine.Child0; script; script = script->Next)
			for (C4PropList *props = script->GetPropList(); props; props = props->GetPrototype())
			for (auto fname = props->EnumerateOwnFuncs(); fname; fname = props->EnumerateOwnFuncs(fname))
			{
				C4Value val;
				if (!props->GetPropertyByS(fname, &val)) continue;
				auto func = val.getFunction();
				if (!func) continue;
				auto sfunc = func->SFunc();
				if (!sfunc) continue;
				if (sfunc->pOrgScript != sh) continue;
				for (auto chunk = sfunc->GetCode(); chunk->bccType != AB_EOFN; chunk++)
				{
					if (chunk->bccType == AB_DEBUG)
					{
						int lineOfThisOne = sfunc->GetLineOfCode(chunk);
						if (lineOfThisOne == line)
						{
							found = chunk;
							goto Found;
						}
					}
				}
			}
			Found:
			if (found)
				found->Par.i = !found->Par.i; // activate breakpoint
			else
				return ProcessLineResult(false, "Can't set breakpoint (wrong line?)");
		}
		else
			return ProcessLineResult(false, "Can't find script");
	}
	else if (SEqualNoCase(szCmd, "SST"))
	{
		std::list<StdStrBuf*>::iterator it = StackTrace.begin();
		for (it++; it != StackTrace.end(); it++)
		{
			SendLine("AT", (*it)->getData());
		}
		SendLine("EST");
	}
	else if (SEqualNoCase(szCmd, "VAR"))
	{
		
		C4Value *val = NULL;
		int varIndex;
		C4AulScriptContext* pCtx = pExec->GetContext(pExec->GetContextDepth() - 1);
		if (pCtx)
		{
			if ((varIndex = pCtx->Func->ParNamed.GetItemNr(szData)) != -1)
			{
				val = &pCtx->Pars[varIndex];
			}
			else if ((varIndex = pCtx->Func->VarNamed.GetItemNr(szData)) != -1)
			{
				val = &pCtx->Vars[varIndex];
			}
		}
		const char* typeName = val ? GetC4VName(val->GetType()) : "any";
		StdStrBuf output = FormatString("%s %s %s", szData, typeName, val ? val->GetDataString().getData() : "Unknown");
		SendLine("VAR", output.getData());
	}
	else
		return ProcessLineResult(false, "Can't do that");
	
	return ProcessLineResult(true, "");
}