コード例 #1
0
ファイル: AssetLoader.cpp プロジェクト: kevindqc/Helium
bool Helium::AssetIdentifier::Identify( Reflect::Object* object, Name& identity )
{
	Asset *pAsset = Reflect::SafeCast<Asset>(object);

	if ( pAsset )
	{
		identity.Set(pAsset->GetPath().ToString());
		HELIUM_TRACE( TraceLevels::Info, TXT( "Identifying object [%s]\n" ), identity.Get() );
		return true;
	}
	else if ( object )
	{
		HELIUM_TRACE( TraceLevels::Info, TXT( "Deferring identification of object of type [%s]\n" ), object->GetMetaClass()->m_Name );
	}

	return false;
}
コード例 #2
0
ファイル: Asset.cpp プロジェクト: Fantasticer/Helium
/// Create a type object.
///
/// @param[in] name          Type name.
/// @param[in] pTypePackage  Package in which the template object should be stored.
/// @param[in] pParent       Parent type.
/// @param[in] pTemplate     Template object.
/// @param[in] flags         Type flags.
///
/// @return  Pointer to the type object if created successfully, null if not.
///
/// @see Unregister()
// PMD: Removing const because:
// - Objects must be able to have properties of the same type as the outer type (i.e. Asset has reference to Asset that is the template)
// - So, s_MetaClass must be set before calling PopulateMetaType
// - So, this function must return a pointer that PopulateMetaType can work on, rather than calling PopulateMetaType directly
//   - If not for this restriction, I'd want to see if we could call MetaClass::Create and Composite::Create, rather than doing duplicate set-up work here
// - To prevent un-consting parameter to PopulateMetaType, making AssetType return non-const
AssetType* AssetType::Create(
	const Reflect::MetaClass* pClass,
	Package* pTypePackage,
	const AssetType* pParent,
	Asset* pTemplate,
	uint32_t flags )
{
	HELIUM_ASSERT( pClass );
	HELIUM_ASSERT( pTypePackage );
	HELIUM_ASSERT( pTemplate );

	Name name;
	name.Set( pClass->m_Name );
	HELIUM_ASSERT( !name.IsEmpty() );

	// Register the template object with the object system.
	if( !Asset::RegisterObject( pTemplate ) )
	{
		HELIUM_TRACE(
			TraceLevels::Error,
			TXT( "AssetType::Initialize(): Failed to register type \"%s\" template object.\n" ),
			*name );

		return NULL;
	}

	// Set up the template object name, and set this object as its parent.
	Asset::RenameParameters nameParameters;
	nameParameters.name = name;
	nameParameters.spOwner = pTypePackage;
	if( !pTemplate->Rename( nameParameters ) )
	{
		HELIUM_TRACE(
			TraceLevels::Error,
			TXT( "AssetType::Initialize(): Failed to set type \"%s\" template object name and owner.\n" ),
			*name );

		Asset::UnregisterObject( pTemplate );

		return NULL;
	}

	// Flag the object as the default template object for the type being created.
	pTemplate->SetFlags( 
		Asset::FLAG_DEFAULT_TEMPLATE | 
		Asset::FLAG_TRANSIENT | 
		Asset::FLAG_PRELOADED | 
		Asset::FLAG_LINKED |
		Asset::FLAG_PRECACHED |
		Asset::FLAG_LOADED);

	// Create the type object and store its parameters.
	AssetType* pType = new AssetType;
	HELIUM_ASSERT( pType );
	pType->m_class = pClass;
	pClass->m_Tag = pType;
	const_cast< Reflect::MetaClass* >( pType->m_class )->m_Default = pTemplate;
	const_cast< Reflect::MetaClass* >( pType->m_class )->MetaStruct::m_Default = pTemplate;
	pType->m_name = name;
	pType->m_flags = flags;

	// Lazily initialize the lookup map.  Note that this is not inherently thread-safe, but there should always be
	// at least one type registered before any sub-threads are spawned.
	if( !sm_pLookupMap )
	{
		sm_pLookupMap = new LookupMap;
		HELIUM_ASSERT( sm_pLookupMap );
	}

	// Register the type (note that a type with the same name should not already exist in the lookup map).
	LookupMap::Iterator typeIterator;
	HELIUM_VERIFY( sm_pLookupMap->Insert( typeIterator, KeyValue< Name, AssetTypePtr >( pType->GetName(), pType ) ) );

	return pType;
}
コード例 #3
0
ファイル: AssetPath.cpp プロジェクト: KETMGaming/Helium
/// Parse a string into separate path name components.
///
/// @param[in]  pString            String to parse.  This must *not* be empty.
/// @param[in]  rStackHeap         Stack memory heap from which to allocate the resulting name array.
/// @param[out] rpNames            Parsed array of names, in reverse order (top-level path name stored at the end of
///                                the array).  Note that this will be allocated using the given heap and must be
///                                deallocated by the caller.
/// @param[out] rpInstanceIndices  Parsed array of instance indices, with each index corresponding to each name
///                                entry in the parsed names array.  This is also allocated using the given heap and
///                                must be deallocated by the caller.
/// @param[out] rNameCount         Number of names in the parsed array.
/// @param[out] rPackageCount      Number of names specifying packages.
///
/// @return  True if the string was parsed successfully, false if not.
bool AssetPath::Parse(
	const char* pString,
	StackMemoryHeap<>& rStackHeap,
	Name*& rpNames,
	uint32_t*& rpInstanceIndices,
	size_t& rNameCount,
	size_t& rPackageCount )
{
	HELIUM_ASSERT( pString );
	HELIUM_ASSERT( pString[ 0 ] != TXT( '\0' ) );

	rpNames = NULL;
	rpInstanceIndices = NULL;
	rNameCount = 0;
	rPackageCount = 0;

	// Make sure the entry specifies an absolute path.
	if( pString[ 0 ] != HELIUM_PACKAGE_PATH_CHAR && pString[ 0 ] != HELIUM_OBJECT_PATH_CHAR )
	{
		HELIUM_TRACE(
			TraceLevels::Warning,
			TXT( "AssetPath: FilePath string \"%s\" does not contain a leading path separator.\n" ),
			pString );

		return false;
	}

	// Count the number of path separators in the path.
	size_t nameCount = 0;
	size_t packageCount = 0;

	size_t nameLengthMax = 0;

	const char* pTestCharacter = pString;
	const char* pNameStartPos = pTestCharacter;
	for( ; ; )
	{
		char character = *pTestCharacter;
		if( character == TXT( '\0' ) )
		{
			size_t nameLength = static_cast< size_t >( pTestCharacter - pNameStartPos );
			if( nameLength > nameLengthMax )
			{
				nameLengthMax = nameLength;
			}

			break;
		}

		if( character == HELIUM_PACKAGE_PATH_CHAR )
		{
			if( packageCount != nameCount )
			{
				HELIUM_TRACE(
					TraceLevels::Warning,
					( TXT( "AssetPath: Unexpected package path separator at character %" ) PRIdPD TXT( " of " )
					TXT( "path string \"%s\".\n" ) ),
					pTestCharacter - pString,
					pString );

				return false;
			}

			++nameCount;
			++packageCount;

			size_t nameLength = static_cast< size_t >( pTestCharacter - pNameStartPos );
			if( nameLength > nameLengthMax )
			{
				nameLengthMax = nameLength;
			}

			pNameStartPos = pTestCharacter + 1;
		}
		else if( character == HELIUM_OBJECT_PATH_CHAR )
		{
			++nameCount;

			size_t nameLength = static_cast< size_t >( pTestCharacter - pNameStartPos );
			if( nameLength > nameLengthMax )
			{
				nameLengthMax = nameLength;
			}

			pNameStartPos = pTestCharacter + 1;
		}

		++pTestCharacter;
	}

	HELIUM_ASSERT( nameCount != 0 );

	// Parse the names from the string.
	rpNames = static_cast< Name* >( rStackHeap.Allocate( sizeof( Name ) * nameCount ) );
	HELIUM_ASSERT( rpNames );

	rpInstanceIndices = static_cast< uint32_t* >( rStackHeap.Allocate( sizeof( uint32_t ) * nameCount ) );
	HELIUM_ASSERT( rpInstanceIndices );

	char* pTempNameString = static_cast< char* >( rStackHeap.Allocate(
		sizeof( char ) * ( nameLengthMax + 1 ) ) );
	HELIUM_ASSERT( pTempNameString );
	char* pTempNameCharacter = pTempNameString;

	Name* pTargetName = &rpNames[ nameCount - 1 ];
	uint32_t* pTargetIndex = &rpInstanceIndices[ nameCount - 1 ];

	bool bParsingName = true;

	pTestCharacter = pString + 1;
	for( ; ; )
	{
		char character = *pTestCharacter;
		if( character != HELIUM_PACKAGE_PATH_CHAR && character != HELIUM_OBJECT_PATH_CHAR && character != TXT( '\0' ) )
		{
			// Make sure the character is a valid number when parsing the instance index.
			if( !bParsingName && ( character < TXT( '0' ) || character > TXT( '9' ) ) )
			{
				HELIUM_TRACE(
					TraceLevels::Error,
					TXT( "AssetPath: Encountered non-numeric instance index value in path string \"%s\".\n" ),
					*pString );

				return false;
			}

			if( bParsingName && character == HELIUM_INSTANCE_PATH_CHAR )
			{
				// Encountered a separator for the instance index, so begin parsing it.
				*pTempNameCharacter = TXT( '\0' );

				pTargetName->Set( pTempNameString );
				--pTargetName;

				pTempNameCharacter = pTempNameString;
				bParsingName = false;
			}
			else
			{
				HELIUM_ASSERT( static_cast< size_t >( pTempNameCharacter - pTempNameString ) < nameLengthMax );
				*pTempNameCharacter = character;
				++pTempNameCharacter;
			}
		}
		else
		{
			*pTempNameCharacter = TXT( '\0' );

			if( bParsingName )
			{
				pTargetName->Set( pTempNameString );
				--pTargetName;

				SetInvalid( *pTargetIndex );
				--pTargetIndex;
			}
			else
			{
				if( pTempNameCharacter == pTempNameString )
				{
					HELIUM_TRACE(
						TraceLevels::Error,
						TXT( "AssetPath: Empty instance index encountered in path string \"%s\".\n" ),
						pString );

					return false;
				}

				if( pTempNameCharacter - pTempNameString > 1 && *pTempNameString == TXT( '0' ) )
				{
					HELIUM_TRACE(
						TraceLevels::Error,
						( TXT( "AssetPath: Encountered instance index \"%s\" with leading zeros in path string " )
						TXT( "\"%s\".\n" ) ),
						pTempNameString,
						pString );

					return false;
				}

				int parseCount = StringScan( pTempNameString, TXT( "%" ) SCNu32, pTargetIndex );
				if( parseCount != 1 )
				{
					HELIUM_TRACE(
						TraceLevels::Error,
						TXT( "AssetPath: Failed to parse object instance index \"%s\" in path string \"%s\".\n" ),
						pTempNameString,
						pString );

					return false;
				}

				if( IsInvalid( *pTargetIndex ) )
				{
					HELIUM_TRACE(
						TraceLevels::Error,
						TXT( "AssetPath: Instance index \"%s\" in path string \"%s\" is a reserved value.\n" ),
						pTempNameString,
						pString );

					return false;
				}

				--pTargetIndex;
			}

			if( character == TXT( '\0' ) )
			{
				break;
			}

			pTempNameCharacter = pTempNameString;
			bParsingName = true;
		}

		++pTestCharacter;
	}

	rNameCount = nameCount;
	rPackageCount = packageCount;

	return true;
}