Exemplo n.º 1
0
void EntityClass_resolveInheritance( EntityClass* derivedClass ){
	if ( derivedClass->inheritanceResolved == false ) {
		derivedClass->inheritanceResolved = true;
		EntityClasses::iterator i = g_EntityClassDoom3_classes.find( derivedClass->m_parent.front().c_str() );
		if ( i == g_EntityClassDoom3_classes.end() ) {
			globalErrorStream() << "failed to find entityDef " << makeQuoted( derivedClass->m_parent.front().c_str() ) << " inherited by "  << makeQuoted( derivedClass->m_name.c_str() ) << "\n";
		}
		else
		{
			EntityClass* parentClass = ( *i ).second;
			EntityClass_resolveInheritance( parentClass );
			if ( !derivedClass->colorSpecified ) {
				derivedClass->colorSpecified = parentClass->colorSpecified;
				derivedClass->color = parentClass->color;
			}
			if ( !derivedClass->sizeSpecified ) {
				derivedClass->sizeSpecified = parentClass->sizeSpecified;
				derivedClass->mins = parentClass->mins;
				derivedClass->maxs = parentClass->maxs;
				derivedClass->fixedsize = parentClass->fixedsize;
			}

			for ( EntityClassAttributes::iterator j = parentClass->m_attributes.begin(); j != parentClass->m_attributes.end(); ++j )
			{
				EntityClass_insertAttribute( *derivedClass, ( *j ).first.c_str(), ( *j ).second );
			}
		}
	}
}
Exemplo n.º 2
0
/**
 * Add a new EntityClassAttribute to entity class based on given definition
 * @param e entity class to add attribute to
 * @param keydef definition parsed from entities.ufo with information about type,
 * default values and mandatory state.
 * @note opposed to old parsing code this adds attributes for all definitions,
 * not only for the ones that get special treatment in gui.
 */
void EntityClassScannerUFO::parseAttribute (EntityClass *e, const entityKeyDef_t* keydef)
{
	const bool mandatory = (keydef->flags & ED_MANDATORY);
	/* we use attribute key as its type, only for some types this is really used */
	std::string attributeName = keydef->name;
	std::string value = "";
	std::string desc = "";
	if (keydef->defaultVal)
		value = keydef->defaultVal;
	if (keydef->desc)
		desc = keydef->desc;
	int typeFlag = keydef->flags & ED_KEY_TYPE;

	std::string type = attributeName;

	if (attributeName == "noise")
		type = "sound";
	else if (attributeName == "_color" || attributeName == "color")
		type = "colour";
	else if (attributeName == "target")
		type = "entity";
	else if (typeFlag & ED_TYPE_FLOAT) {
		if (keydef->vLen == 3)
			type = "vector3";
		else if (keydef->vLen == 1)
			type = "float";
	} else if (typeFlag & ED_TYPE_INT) {
		// integer
	} else if (typeFlag == 0 || (typeFlag & ED_TYPE_STRING)) {
		// string
	}

	EntityClassAttribute attribute = EntityClassAttribute(type, attributeName, mandatory, value, desc);
	EntityClass_insertAttribute(*e, attributeName, attribute);
}
Exemplo n.º 3
0
static bool EntityClass_parse( EntityClass& entityClass, Tokeniser& tokeniser ){
	PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, entityClass.m_name ) );

	PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser, "{" ) );
	tokeniser.nextLine();

	StringOutputStream usage( 256 );
	StringOutputStream description( 256 );
	CopiedString* currentDescription = 0;
	StringOutputStream* currentString = 0;

	for (;; )
	{
		const char* key;
		PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, key ) );

		const char* last = string_findFirstSpaceOrTab( key );
		CopiedString first( StringRange( key, last ) );

		if ( !string_empty( last ) ) {
			last = string_findFirstNonSpaceOrTab( last );
		}

		if ( currentString != 0 && string_equal( key, "\\" ) ) {
			tokeniser.nextLine();
			*currentString << " ";
			PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, *currentString ) );
			continue;
		}

		if ( currentDescription != 0 ) {
			*currentDescription = description.c_str();
			description.clear();
			currentDescription = 0;
		}
		currentString = 0;

		if ( string_equal( key, "}" ) ) {
			tokeniser.nextLine();
			break;
		}
		else if ( string_equal( key, "model" ) ) {
			const char* token;
			PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, token ) );
			entityClass.fixedsize = true;
			StringOutputStream buffer( 256 );
			buffer << PathCleaned( token );
			entityClass.m_modelpath = buffer.c_str();
		}
		else if ( string_equal( key, "editor_color" ) ) {
			const char* value;
			PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, value ) );
			if ( !string_empty( value ) ) {
				entityClass.colorSpecified = true;
				bool success = string_parse_vector3( value, entityClass.color );
				ASSERT_MESSAGE( success, "editor_color: parse error" );
			}
		}
		else if ( string_equal( key, "editor_ragdoll" ) ) {
			//bool ragdoll = atoi(tokeniser.getToken()) != 0;
			PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser ) );
		}
		else if ( string_equal( key, "editor_mins" ) ) {
			entityClass.sizeSpecified = true;
			const char* value;
			PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, value ) );
			if ( !string_empty( value ) && !string_equal( value, "?" ) ) {
				entityClass.fixedsize = true;
				bool success = string_parse_vector3( value, entityClass.mins );
				ASSERT_MESSAGE( success, "editor_mins: parse error" );
			}
		}
		else if ( string_equal( key, "editor_maxs" ) ) {
			entityClass.sizeSpecified = true;
			const char* value;
			PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, value ) );
			if ( !string_empty( value ) && !string_equal( value, "?" ) ) {
				entityClass.fixedsize = true;
				bool success = string_parse_vector3( value, entityClass.maxs );
				ASSERT_MESSAGE( success, "editor_maxs: parse error" );
			}
		}
		else if ( string_equal( key, "editor_usage" ) ) {
			PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, usage ) );
			currentString = &usage;
		}
		else if ( string_equal_n( key, "editor_usage", 12 ) ) {
			PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, usage ) );
			currentString = &usage;
		}
		else if ( string_equal( key, "editor_rotatable" )
				  || string_equal( key, "editor_showangle" )
				  || string_equal( key, "editor_showangles" ) // typo? in prey movables.def
				  || string_equal( key, "editor_mover" )
				  || string_equal( key, "editor_model" )
				  || string_equal( key, "editor_material" )
				  || string_equal( key, "editor_combatnode" )
				  || ( !string_empty( last ) && string_equal( first.c_str(), "editor_gui" ) )
				  || string_equal_n( key, "editor_copy", 11 ) ) {
			PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser ) );
		}
		else if ( !string_empty( last ) && ( string_equal( first.c_str(), "editor_var" ) || string_equal( first.c_str(), "editor_string" ) ) ) {
			EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, last ).second;
			attribute.m_type = "string";
			currentDescription = &attribute.m_description;
			currentString = &description;
			PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, description ) );
		}
		else if ( !string_empty( last ) && string_equal( first.c_str(), "editor_float" ) ) {
			EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, last ).second;
			attribute.m_type = "string";
			currentDescription = &attribute.m_description;
			currentString = &description;
			PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, description ) );
		}
		else if ( !string_empty( last ) && string_equal( first.c_str(), "editor_snd" ) ) {
			EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, last ).second;
			attribute.m_type = "sound";
			currentDescription = &attribute.m_description;
			currentString = &description;
			PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, description ) );
		}
		else if ( !string_empty( last ) && string_equal( first.c_str(), "editor_bool" ) ) {
			EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, last ).second;
			attribute.m_type = "boolean";
			currentDescription = &attribute.m_description;
			currentString = &description;
			PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, description ) );
		}
		else if ( !string_empty( last ) && string_equal( first.c_str(), "editor_int" ) ) {
			EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, last ).second;
			attribute.m_type = "integer";
			currentDescription = &attribute.m_description;
			currentString = &description;
			PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, description ) );
		}
		else if ( !string_empty( last ) && string_equal( first.c_str(), "editor_model" ) ) {
			EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, last ).second;
			attribute.m_type = "model";
			currentDescription = &attribute.m_description;
			currentString = &description;
			PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, description ) );
		}
		else if ( !string_empty( last ) && string_equal( first.c_str(), "editor_color" ) ) {
			EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, last ).second;
			attribute.m_type = "color";
			currentDescription = &attribute.m_description;
			currentString = &description;
			PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, description ) );
		}
		else if ( !string_empty( last ) && ( string_equal( first.c_str(), "editor_material" ) || string_equal( first.c_str(), "editor_mat" ) ) ) {
			EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, last ).second;
			attribute.m_type = "shader";
			currentDescription = &attribute.m_description;
			currentString = &description;
			PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, description ) );
		}
		else if ( string_equal( key, "inherit" ) ) {
			entityClass.inheritanceResolved = false;
			ASSERT_MESSAGE( entityClass.m_parent.empty(), "only one 'inherit' supported per entityDef" );
			const char* token;
			PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, token ) );
			entityClass.m_parent.push_back( token );
		}
		// begin quake4-specific keys
		else if ( string_equal( key, "editor_targetonsel" ) ) {
			//const char* value =
			PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser ) );
		}
		else if ( string_equal( key, "editor_menu" ) ) {
			//const char* value =
			PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser ) );
		}
		else if ( string_equal( key, "editor_ignore" ) ) {
			//const char* value =
			PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser ) );
		}
		// end quake4-specific keys
		// begin ignore prey (unknown/unused?) entity keys
		else if ( string_equal( key, "editor_light" )
				  || string_equal( key, "editor_def def_debrisspawner" )
				  || string_equal( key, "editor_def def_drop" )
				  || string_equal( key, "editor_def def_guihand" )
				  || string_equal( key, "editor_def def_mine" ) ) {
			//const char* value =
			PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser ) );
		}
		// end ignore prey entity keys
		else
		{
			CopiedString tmp( key );
			if ( string_equal_n( key, "editor_", 7 ) ) {
				globalErrorStream() << "unsupported editor key " << makeQuoted( key ) ;
			}
			EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, key ).second;
			attribute.m_type = "string";
			const char* value;
			PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, value ) );
			if ( string_equal( value, "}" ) ) { // hack for quake4 powerups.def bug
				globalErrorStream() << "entityDef " << makeQuoted( entityClass.m_name.c_str() ) << " key " << makeQuoted( tmp.c_str() ) << " has no value\n";
				break;
			}
			else
			{
				attribute.m_value = value;
			}
		}
		tokeniser.nextLine();
	}

	entityClass.m_comments = usage.c_str();

	if ( string_equal( entityClass.m_name.c_str(), "light" ) ) {
		{
			EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, "light_radius" ).second;
			attribute.m_type = "vector3";
			attribute.m_value = "300 300 300";
		}
		{
			EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, "light_center" ).second;
			attribute.m_type = "vector3";
		}
		{
			EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, "noshadows" ).second;
			attribute.m_type = "boolean";
			attribute.m_value = "0";
		}
		{
			EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, "nospecular" ).second;
			attribute.m_type = "boolean";
			attribute.m_value = "0";
		}
		{
			EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, "nodiffuse" ).second;
			attribute.m_type = "boolean";
			attribute.m_value = "0";
		}
		{
			EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, "falloff" ).second;
			attribute.m_type = "real";
		}
	}

	return true;
}
Exemplo n.º 4
0
/**
 * Creates a new entityclass for given parsed definition
 * @param entityDef parsed definition information to use
 * @return a new entity class or 0 if something was wrong with definition
 */
EntityClass *EntityClassScannerUFO::initFromDefinition (const entityDef_t* definition)
{
	g_debug("Creating entity class for entity definition '%s'\n", definition->classname);

	EntityClass* e = Eclass_Alloc();
	e->free = &Eclass_Free;
	e->m_name = definition->classname;

	for (int idx = 0; idx < definition->numKeyDefs; idx++) {
		const entityKeyDef_t* keydef = &definition->keyDefs[idx];
		const std::string keyName = keydef->name;

		if (keyName == "color") {
			//not using _color as this is a valid attribute flag
			// grab the color, reformat as texture name
			const int r = sscanf(keydef->desc, "%f %f %f", &e->color[0], &e->color[1], &e->color[2]);
			if (r != 3) {
				g_message("Invalid color token given\n");
				return 0;
			}
		} else if (keyName == "size") {
			e->fixedsize = true;
			const int r = sscanf(keydef->desc, "%f %f %f %f %f %f", &e->mins[0], &e->mins[1], &e->mins[2], &e->maxs[0],
					&e->maxs[1], &e->maxs[2]);
			if (r != 6) {
				g_message("Invalid size token given\n");
				return 0;
			}
		} else if (keyName == "description") {
			e->m_comments = keydef->desc;
		} else if (keyName == "spawnflags") {
			if (keydef->flags & ED_ABSTRACT) {
				/* there are two keydefs, abstract holds the valid levelflags, the other one default value and type */
				const char* flags = keydef->desc;
				parseFlags(e, &flags);
			} else {
				parseAttribute(e, keydef);
			}
		} else if (keyName == "classname") {
			/* ignore, read from head */
			continue;
		} else if (keyName == "model") {
			/** @todo what does that modelpath stuff do? it does not read anything from keydef */
			e->m_modelpath = os::standardPath(e->m_modelpath);
			const bool mandatory = (keydef->flags & ED_MANDATORY);
			EntityClass_insertAttribute(*e, "model", EntityClassAttribute("model", "model", mandatory));
		} else {
			/* all other keys are valid attribute keys */
			parseAttribute(e, keydef);
		}
	}

#if 0
	/**
	 * @todo direction and angle are 2 types used for different display
	 * (see entityinspector DirectionAttribute and AngleAttribute)
	 * the problem is that different entities have "angle" property, but different defines what values are valid
	 * which is actually not reflected by this code. Perhaps we should introduce different types for these representations.
	 */
	EntityClassAttribute *angle = e->getAttribute("angle");
	if (angle) {
		if (e->fixedsize) {
			angle->name = _("Yaw Angle");
		} else {
			angle->name = _("Direction");
		}
	}
#endif
	eclass_capture_state(e);

	return e;
}