Пример #1
0
static void ParseFloor (FScanner &sc)
{
	FTextureID picnum;
	int terrain;

	bool opt = sc.CheckString("optional");
	sc.MustGetString ();

	picnum = TexMan.CheckForTexture (sc.String, FTexture::TEX_Flat,
		FTextureManager::TEXMAN_Overridable|FTextureManager::TEXMAN_TryAny);

	if (!picnum.Exists())
	{
		if (!opt)
		{
			Printf("Unknown flat %s\n", sc.String);
		}
		sc.MustGetString();
		return;
	}
	sc.MustGetString ();
	terrain = P_FindTerrain (sc.String);
	if (terrain == -1)
	{
		Printf ("Unknown terrain %s\n", sc.String);
		terrain = 0;
	}
	TerrainTypes.Set(picnum.GetIndex(), terrain);
}
Пример #2
0
static TArray<FString> PSR_ReadBaseInstalls(FScanner &sc)
{
	TArray<FString> result;

	// Get a list of possible install directories.
	while(sc.GetToken())
	{
		if(sc.TokenType == '}')
			break;

		sc.TokenMustBe(TK_StringConst);
		FString key(sc.String);
		if(key.Left(18).CompareNoCase("BaseInstallFolder_") == 0)
		{
			sc.MustGetToken(TK_StringConst);
			result.Push(FString(sc.String) + "/steamapps/common");
		}
		else
		{
			if(sc.CheckToken('{'))
				PSR_FindEndBlock(sc);
			else
				sc.MustGetToken(TK_StringConst);
		}
	}

	return result;
}
Пример #3
0
bool FIntermissionActionWiper::ParseKey(FScanner &sc)
{
	struct WipeType
	{
		const char *Name;
		gamestate_t Type;
	}
	const FT[] = {
		{ "Crossfade", GS_FORCEWIPEFADE },
		{ "Melt", GS_FORCEWIPEMELT },
		{ "Burn", GS_FORCEWIPEBURN },
		{ "Default", GS_FORCEWIPE },
		{ NULL, GS_FORCEWIPE }
	};

	if (sc.Compare("WipeType"))
	{
		sc.MustGetToken('=');
		sc.MustGetToken(TK_Identifier);
		int v = sc.MatchString(&FT[0].Name, sizeof(FT[0]));
		if (v != -1) mWipeType = FT[v].Type;
		return true;
	}
	else return Super::ParseKey(sc);
}
Пример #4
0
static void AddOneKey(Keygroup *keygroup, PClassActor *mi, FScanner &sc)
{
	if (mi)
	{
		// Any inventory item can be used to unlock a door
		if (mi->IsDescendantOf(RUNTIME_CLASS(AInventory)))
		{
			OneKey k = {mi,1};
			keygroup->anykeylist.Push (k);

			//... but only keys get key numbers!
			if (mi->IsDescendantOf(RUNTIME_CLASS(AKey)))
			{
				if (!ignorekey &&
					static_cast<AKey*>(GetDefaultByType(mi))->KeyNumber == 0)
				{
					static_cast<AKey*>(GetDefaultByType(mi))->KeyNumber=++currentnumber;
				}
			}
		}
		else
		{
			sc.ScriptError("'%s' is not an inventory item", sc.String);
		}
	}
	else
	{
		sc.ScriptError("Unknown item '%s'", sc.String);
	}
}
Пример #5
0
static TArray<FString> ParseSteamRegistry(const char* path)
{
	TArray<FString> dirs;

	// Read registry data
	FScanner sc;
	if (sc.OpenFile(path))
	{
		sc.SetCMode(true);

		// Find the SteamApps listing
		if (PSR_FindAndEnterBlock(sc, "InstallConfigStore"))
		{
			if (PSR_FindAndEnterBlock(sc, "Software"))
			{
				if (PSR_FindAndEnterBlock(sc, "Valve"))
				{
					if (PSR_FindAndEnterBlock(sc, "Steam"))
					{
						dirs = PSR_ReadBaseInstalls(sc);
					}
					PSR_FindEndBlock(sc);
				}
				PSR_FindEndBlock(sc);
			}
			PSR_FindEndBlock(sc);
		}
	}
	return dirs;
}
Пример #6
0
static void ParseOptionSettings(FScanner &sc)
{
	sc.MustGetStringName("{");
	while (!sc.CheckString("}"))
	{
		sc.MustGetString();
		if (sc.Compare("else"))
		{
			SkipSubBlock(sc);
		}
		else if (sc.Compare("ifgame"))
		{
			if (!CheckSkipGameBlock(sc))
			{
				// recursively parse sub-block
				ParseOptionSettings(sc);
			}
		}
		else if (sc.Compare("Linespacing"))
		{
			sc.MustGetNumber();
			OptionSettings.mLinespacing = sc.Number;
		}
		else if (sc.Compare("LabelOffset"))
		{
			sc.MustGetNumber();
			// ignored
		}
		else
		{
			sc.ScriptError("Unknown keyword '%s'", sc.String);
		}
	}
}
Пример #7
0
void ParseFunctionDef(FScanner &sc, PClassActor *cls, FName funcname,
	TArray<PType *> &rets, DWORD funcflags)
{
	assert(cls != NULL);

	const AFuncDesc *afd;
	TArray<PType *> args;
	TArray<DWORD> argflags;

	afd = FindFunction(funcname);
	if (afd == NULL)
	{
		sc.ScriptMessage ("The function '%s' has not been exported from the executable.", funcname.GetChars());
		FScriptPosition::ErrorCounter++;
	}
	sc.MustGetToken('(');

	SetImplicitArgs(&args, &argflags, cls, funcflags);
	ParseArgListDef(sc, cls, args, argflags);

	if (afd != NULL)
	{
		PFunction *sym = new PFunction(funcname);
		sym->AddVariant(NewPrototype(rets, args), argflags, *(afd->VMPointer));
		sym->Flags = funcflags;
		if (cls->Symbols.AddSymbol(sym) == NULL)
		{
			delete sym;
			sc.ScriptMessage ("'%s' is already defined in class '%s'.",
				funcname.GetChars(), cls->TypeName.GetChars());
			FScriptPosition::ErrorCounter++;
		}
	}
}
Пример #8
0
void FTeam::ParseTeamInfo ()
{
	int iLump, iLastLump = 0;

	Teams.Clear();
	while ((iLump = Wads.FindLump ("TEAMINFO", &iLastLump)) != -1)
	{
		FScanner Scan (iLump);

		while (Scan.GetString ())
		{
			if (Scan.Compare ("ClearTeams"))
				ClearTeams ();
			else if (Scan.Compare ("Team"))
				ParseTeamDefinition (Scan);
			else
				Scan.ScriptError ("ParseTeamInfo: Unknown team command '%s'.\n", Scan.String);
		}
	}

	if (Teams.Size () < 2)
		I_FatalError ("ParseTeamInfo: At least two teams must be defined in TEAMINFO.");
	else if (Teams.Size () > (unsigned)TEAM_MAXIMUM)
		I_FatalError ("ParseTeamInfo: Too many teams defined. (Maximum: %d)", TEAM_MAXIMUM);
}
Пример #9
0
//==========================================================================
//
// Processes a flag. Also used by olddecorations.cpp
//
//==========================================================================
void HandleActorFlag(FScanner &sc, Baggage &bag, const char *part1, const char *part2, int mod)
{
	FFlagDef *fd;

	if ( (fd = FindFlag (bag.Info, part1, part2)) )
	{
		AActor *defaults = (AActor*)bag.Info->Defaults;
		if (fd->structoffset == -1)	// this is a deprecated flag that has been changed into a real property
		{
			HandleDeprecatedFlags(defaults, bag.Info, mod=='+', fd->flagbit);
		}
		else
		{
			ModActorFlag(defaults, fd, mod == '+');
		}
	}
	else
	{
		if (part2 == NULL)
		{
			sc.ScriptMessage("\"%s\" is an unknown flag\n", part1);
		}
		else
		{
			sc.ScriptMessage("\"%s.%s\" is an unknown flag\n", part1, part2);
		}
		FScriptPosition::ErrorCounter++;
	}
}
Пример #10
0
static FString ParseMultiString(FScanner &scanner, int error)
{
	FString build;
	
	if (scanner.CheckToken(TK_Identifier))
	{
		if (!stricmp(scanner.String, "clear"))
		{
			return "-";
		}
		else
		{
			scanner.ScriptError("Either 'clear' or string constant expected");
		}
	}
	
	do
	{
		scanner.MustGetToken(TK_StringConst);
		if (build.Len() > 0) build += "\n";
		build += scanner.String;
	} 
	while (scanner.CheckToken(','));
	return build;
}
Пример #11
0
void FTextureManager::ParseRangeAnim (FScanner &sc, FTextureID picnum, int usetype, bool missing)
{
	int type;
	FTextureID framenum;
	DWORD min, max;

	type = FAnimDef::ANIM_Forward;
	framenum = ParseFramenum (sc, picnum, usetype, missing);
	ParseTime (sc, min, max);

	if (framenum == picnum || !picnum.Exists())
	{
		return;		// Animation is only one frame or does not exist
	}
	if (framenum < picnum)
	{
		type = FAnimDef::ANIM_Backward;
		Texture(framenum)->bNoDecals = Texture(picnum)->bNoDecals;
		swapvalues (framenum, picnum);
	}
	if (sc.GetString())
	{
		if (sc.Compare ("Oscillate"))
		{
			type = type == FAnimDef::ANIM_Forward ? FAnimDef::ANIM_OscillateUp : FAnimDef::ANIM_OscillateDown;
		}
		else
		{
			sc.UnGet ();
		}
	}
	AddSimpleAnim (picnum, framenum - picnum + 1, type, min, max - min);
}
Пример #12
0
void SetReplacement(FScanner &sc, FActorInfo *info, FName replaceName)
{
	// Check for "replaces"
	if (replaceName != NAME_None)
	{
		// Get actor name
		const PClass *replacee = PClass::FindClass (replaceName);

		if (replacee == NULL)
		{
			sc.ScriptMessage("Replaced type '%s' not found for %s", replaceName.GetChars(), info->Class->TypeName.GetChars());
			return;
		}
		else if (replacee->ActorInfo == NULL)
		{
			sc.ScriptMessage("Replaced type '%s' for %s is not an actor", replaceName.GetChars(), info->Class->TypeName.GetChars());
			return;
		}
		if (replacee != NULL)
		{
			replacee->ActorInfo->Replacement = info;
			info->Replacee = replacee->ActorInfo;
		}
	}

}
Пример #13
0
void SBarInfo::ParseMugShotBlock(FScanner &sc, FMugShotState &state)
{
	sc.MustGetToken('{');
	while(!sc.CheckToken('}'))
	{
		FMugShotFrame frame;
		bool multiframe = false;
		if(sc.CheckToken('{'))
			multiframe = true;
		do
		{
			sc.MustGetToken(TK_Identifier);
			if(strlen(sc.String) > 5)
				sc.ScriptError("MugShot frames cannot exceed 5 characters.");
			frame.Graphic.Push(sc.String);
		}
		while(multiframe && sc.CheckToken(','));
		if(multiframe)
			sc.MustGetToken('}');
		bool negative = sc.CheckToken('-');
		sc.MustGetToken(TK_IntConst);
		frame.Delay = (negative ? -1 : 1)*sc.Number;
		sc.MustGetToken(';');
		state.Frames.Push(frame);
	}
}
Пример #14
0
void P_ParseAnimatedDoor(FScanner &sc)
{
	const BITFIELD texflags = FTextureManager::TEXMAN_Overridable | FTextureManager::TEXMAN_TryAny;
	FDoorAnimation anim;
	TArray<FTextureID> frames;
	bool error = false;
	FTextureID v;

	sc.MustGetString();
	anim.BaseTexture = TexMan.CheckForTexture (sc.String, FTexture::TEX_Wall, texflags);

	if (!anim.BaseTexture.Exists())
	{
		error = true;
	}

	while (sc.GetString ())
	{
		if (sc.Compare ("opensound"))
		{
			sc.MustGetString ();
			anim.OpenSound = sc.String;
		}
		else if (sc.Compare ("closesound"))
		{
			sc.MustGetString ();
			anim.CloseSound = sc.String;
		}
		else if (sc.Compare ("pic"))
		{
			sc.MustGetString ();
			if (IsNum (sc.String))
			{
				v = anim.BaseTexture + (atoi(sc.String) - 1);
			}
			else
			{
				v = TexMan.CheckForTexture (sc.String, FTexture::TEX_Wall, texflags);
				if (!v.Exists() && anim.BaseTexture.Exists() && !error)
				{
					sc.ScriptError ("Unknown texture %s", sc.String);
				}
				frames.Push (v);
			}
		}
		else
		{
			sc.UnGet ();
			break;
		}
	}
	if (!error)
	{
		anim.TextureFrames = new FTextureID[frames.Size()];
		memcpy (anim.TextureFrames, &frames[0], sizeof(FTextureID) * frames.Size());
		anim.NumTextureFrames = frames.Size();
		DoorAnimations.Push (anim);
	}
}
Пример #15
0
//==========================================================================
//
// Reads an actor definition
//
//==========================================================================
static void ParseActor(FScanner &sc)
{
	PClassActor *info = NULL;
	Baggage bag;

	info = ParseActorHeader(sc, &bag);
	sc.MustGetToken('{');
	while (sc.MustGetAnyToken(), sc.TokenType != '}')
	{
		switch (sc.TokenType)
		{
		case TK_Action:
			ParseActionDef (sc, info);
			break;

		case TK_Const:
			ParseConstant (sc, &info->Symbols, info);
			break;

		case TK_Enum:
			ParseEnum (sc, &info->Symbols, info);
			break;

		case TK_Native:
			ParseNativeFunction (sc, info);
			break;

		case TK_Var:
			ParseUserVariable (sc, &info->Symbols, info);
			break;

		case TK_Identifier:
			ParseActorProperty(sc, bag);
			break;

		case TK_States:
			if (bag.StateSet) 
			{
				sc.ScriptMessage("'%s' contains multiple state declarations", bag.Info->TypeName.GetChars());
				FScriptPosition::ErrorCounter++;
			}
			ParseStates(sc, bag.Info, (AActor *)bag.Info->Defaults, bag);
			bag.StateSet = true;
			break;

		case '+':
		case '-':
			ParseActorFlag(sc, bag, sc.TokenType);
			break;

		default:
			sc.ScriptError("Unexpected '%s' in definition of '%s'", sc.String, bag.Info->TypeName.GetChars());
			break;
		}
	}
	FinishActor(sc, info, bag);
	sc.SetCMode (false);
}
Пример #16
0
static void ParseDamage (FScanner &sc, int keyword, void *fields)
{
	FTerrainDef *def = (FTerrainDef *)fields;

	sc.MustGetString ();
	// Lava is synonymous with Fire here!
	if (sc.Compare("Lava")) def->DamageMOD=NAME_Fire;
	else def->DamageMOD=sc.String;
}
Пример #17
0
static int ParseLumpName(FScanner &scanner, char *buffer)
{
	scanner.MustGetToken(TK_StringConst);
	if (strlen(scanner.String) > 8)
	{
		scanner.ScriptError("String too long. Maximum size is 8 characters.");
		return 0;
	}
	uppercopy(buffer, scanner.String);
	return 1;
}
Пример #18
0
static void SkipSubBlock(FScanner &sc)
{
	sc.MustGetStringName("{");
	int depth = 1;
	while (depth > 0)
	{
		sc.MustGetString();
		if (sc.Compare("{")) depth++;
		if (sc.Compare("}")) depth--;
	}
}
Пример #19
0
static int ParseMapEntry(FScanner &scanner, UMapEntry *val)
{
	scanner.MustGetToken(TK_Identifier);

	val->MapName = scanner.String;
	scanner.MustGetToken('{');
	while(!scanner.CheckToken('}'))
	{
		ParseStandardProperty(scanner, val);
	}
	return 1;
}
Пример #20
0
//==========================================================================
//
// Parses a flag name
//
//==========================================================================
static void ParseActorFlag (FScanner &sc, Baggage &bag, int mod)
{
	sc.MustGetString ();

	FString part1 = sc.String;
	const char *part2 = NULL;
	if (sc.CheckString ("."))
	{
		sc.MustGetString ();
		part2 = sc.String;
	}
	HandleActorFlag(sc, bag, part1, part2, mod);
}
Пример #21
0
int SBarInfo::getSignedInteger(FScanner &sc)
{
	if(sc.CheckToken('-'))
	{
		sc.MustGetToken(TK_IntConst);
		return -sc.Number;
	}
	else
	{
		sc.MustGetToken(TK_IntConst);
		return sc.Number;
	}
}
Пример #22
0
		EColorRange	GetTranslation(FScanner &sc)
		{
			if (!sc.CheckToken(TK_Null)) sc.MustGetToken(TK_Identifier);
			EColorRange returnVal = CR_UNTRANSLATED;
			FString namedTranslation; //we must send in "[translation]"
			const BYTE *trans_ptr;
			namedTranslation.Format("[%s]", sc.String);
			trans_ptr = (const BYTE *)(&namedTranslation[0]);
			if((returnVal = V_ParseFontColor(trans_ptr, CR_UNTRANSLATED, CR_UNTRANSLATED)) == CR_UNDEFINED)
			{
				sc.ScriptError("Missing definition for color %s.", sc.String);
			}
			return returnVal;
		}
Пример #23
0
static void ParseActionDef (FScanner &sc, PClassActor *cls)
{
	unsigned int error = 0;
	FName funcname;
	TArray<PType *> rets;
	
	if (sc.LumpNum == -1 || Wads.GetLumpFile(sc.LumpNum) > 0)
	{
		sc.ScriptMessage ("Action functions can only be imported by internal class and actor definitions!");
		FScriptPosition::ErrorCounter++;
	}

	sc.MustGetToken(TK_Native);
	// check for a return value
	do
	{
		if (sc.CheckToken(TK_Int) || sc.CheckToken(TK_Bool))
		{
			rets.Push(TypeSInt32);
		}
		else if (sc.CheckToken(TK_State))
		{
			rets.Push(TypeState);
		}
		else if (sc.CheckToken(TK_Float))
		{
			rets.Push(TypeFloat64);
		}
	}
	while (sc.CheckToken(','));
	sc.MustGetToken(TK_Identifier);
	funcname = sc.String;
	ParseFunctionDef(sc, cls, funcname, rets, VARF_Method | VARF_Action);
}
Пример #24
0
void MapLoader::InitED()
{
	FString filename = Level->info->EDName;
	FScanner sc;

	if (filename.IsEmpty()) return;
	int lump = Wads.CheckNumForFullName(filename, true, ns_global);
	if (lump == -1) return;
	sc.OpenLumpNum(lump);

	sc.SetCMode(true);
	while (sc.GetString())
	{
		if (sc.Compare("linedef"))
		{
			parseEDLinedef(sc, EDLines);
		}
		else if (sc.Compare("mapthing"))
		{
			parseMapthing(sc, EDThings);
		}
		else if (sc.Compare("sector"))
		{
			parseSector(sc, EDSectors);
		}
		else
		{
			sc.ScriptError("Unknown keyword '%s'", sc.String);
		}
	}
}
Пример #25
0
static void ParseEnum (FScanner &sc, PSymbolTable *symt, PClass *cls)
{
	int currvalue = 0;

	sc.MustGetToken('{');
	while (!sc.CheckToken('}'))
	{
		sc.MustGetToken(TK_Identifier);
		FName symname = sc.String;
		if (sc.CheckToken('='))
		{
			FxExpression *expr = ParseExpression (sc, cls);
			currvalue = expr->EvalExpression(NULL).GetInt();
			delete expr;
		}
		PSymbolConst *sym = new PSymbolConst(symname);
		sym->ValueType = VAL_Int;
		sym->Value = currvalue;
		if (symt->AddSymbol (sym) == NULL)
		{
			delete sym;
			sc.ScriptMessage ("'%s' is already defined in '%s'.",
				symname.GetChars(), cls? cls->TypeName.GetChars() : "Global");
			FScriptPosition::ErrorCounter++;
		}
		// This allows a comma after the last value but doesn't enforce it.
		if (sc.CheckToken('}')) break;
		sc.MustGetToken(',');
		currvalue++;
	}
	sc.MustGetToken(';');
}
Пример #26
0
static void PSR_FindEndBlock(FScanner &sc)
{
	int depth = 1;
	do
	{
		if(sc.CheckToken('}'))
			--depth;
		else if(sc.CheckToken('{'))
			++depth;
		else
			sc.MustGetAnyToken();
	}
	while(depth);
}
Пример #27
0
static void ParseNativeFunction(FScanner &sc, PClassActor *cls)
{
	TArray<PType *> rets(1);

	if (sc.LumpNum == -1 || Wads.GetLumpFile(sc.LumpNum) > 0)
	{
		sc.ScriptMessage ("functions can only be declared by native actors!");
		FScriptPosition::ErrorCounter++;
	}

	// Read the type and make sure it's int or float.
	sc.MustGetAnyToken();
	switch (sc.TokenType)
	{
	case TK_Int:
	case TK_Bool:
		rets.Push(TypeSInt32);
		break;

	case TK_Float:
		rets.Push(TypeFloat64);
		break;

	case TK_Angle_t:
		rets.Push(TypeAngle);
		break;

	case TK_Fixed_t:
		rets.Push(TypeFixed);
		break;

	case TK_State:
		rets.Push(TypeState);
		break;

	case TK_Identifier:
		rets.Push(NewPointer(RUNTIME_CLASS(DObject)));
		// Todo: Object type
		sc.ScriptError("Object type variables not implemented yet!");
		break;

	default:
		sc.ScriptError("Invalid return type %s", sc.String);
		return;
	}
	sc.MustGetToken(TK_Identifier);
	ParseFunctionDef(sc, cls, sc.String, rets, VARF_Method);
}
Пример #28
0
//==========================================================================
//
// Reads an actor definition
//
//==========================================================================
static void ParseActor(FScanner &sc)
{
	FActorInfo * info=NULL;
	Baggage bag;

	info = ParseActorHeader(sc, &bag);
	sc.MustGetToken('{');
	while (sc.MustGetAnyToken(), sc.TokenType != '}')
	{
		switch (sc.TokenType)
		{
		case TK_Action:
			ParseActionDef (sc, info->Class);
			break;

		case TK_Const:
			ParseConstant (sc, &info->Class->Symbols, info->Class);
			break;

		case TK_Enum:
			ParseEnum (sc, &info->Class->Symbols, info->Class);
			break;

		case TK_Native:
			ParseNativeVariable (sc, &info->Class->Symbols, info->Class);
			break;

		case TK_Var:
			ParseUserVariable (sc, &info->Class->Symbols, info->Class);
			break;

		case TK_Identifier:
			ParseActorProperty(sc, bag);
			break;

		case '+':
		case '-':
			ParseActorFlag(sc, bag, sc.TokenType);
			break;

		default:
			sc.ScriptError("Unexpected '%s' in definition of '%s'", sc.String, bag.Info->Class->TypeName.GetChars());
			break;
		}
	}
	FinishActor(sc, info, bag);
	sc.SetCMode (false);
}
Пример #29
0
static void ParseListMenu(FScanner &sc)
{
	sc.MustGetString();

	FListMenuDescriptor *desc = new FListMenuDescriptor;
	desc->mType = MDESC_ListMenu;
	desc->mMenuName = sc.String;
	desc->mSelectedItem = -1;
	desc->mAutoselect = -1;
	desc->mSelectOfsX = DefaultListMenuSettings.mSelectOfsX;
	desc->mSelectOfsY = DefaultListMenuSettings.mSelectOfsY;
	desc->mSelector = DefaultListMenuSettings.mSelector;
	desc->mDisplayTop = DefaultListMenuSettings.mDisplayTop;
	desc->mXpos = DefaultListMenuSettings.mXpos;
	desc->mYpos = DefaultListMenuSettings.mYpos;
	desc->mLinespacing = DefaultListMenuSettings.mLinespacing;
	desc->mNetgameMessage = DefaultListMenuSettings.mNetgameMessage;
	desc->mFont = DefaultListMenuSettings.mFont;
	desc->mFontColor = DefaultListMenuSettings.mFontColor;
	desc->mFontColor2 = DefaultListMenuSettings.mFontColor2;
	desc->mClass = NULL;
	desc->mRedirect = NULL;
	desc->mWLeft = 0;
	desc->mWRight = 0;
	desc->mCenter = false;

	ParseListMenuBody(sc, desc);
	bool scratch = ReplaceMenu(sc, desc);
	if (scratch) delete desc;
}
Пример #30
0
//==========================================================================
//
// This is only here so any shader definition for ZDoomGL can be skipped
// There is no functionality for this stuff!
//
//==========================================================================
bool gl_ParseShader(FScanner &sc)
{
	int  ShaderDepth = 0;

	if (sc.GetString())
	{
		char *tmp;

		tmp = strstr(sc.String, "{");
		while (tmp)
		{
			ShaderDepth++;
			tmp++;
			tmp = strstr(tmp, "{");
		}

		tmp = strstr(sc.String, "}");
		while (tmp)
		{
			ShaderDepth--;
			tmp++;
			tmp = strstr(tmp, "}");
		}

		if (ShaderDepth == 0) return true;
	}
	return false;
}