void ProjectPanel::OnDroppedFiles( const FileDroppedArgs& args ) { FilePath path( args.m_Path ); // it's a project file if ( CaseInsensitiveCompareString( path.Extension().c_str(), TXT( "HeliumProject" ) ) == 0 ) { wxGetApp().GetFrame()->OpenProject( path ); } else if ( !m_Project ) { int32_t result = wxMessageBox( wxT( "You don't have a project loaded, but you're trying to add files.\nWould you like to create a new project?" ), wxT( "No Project Loaded" ), wxYES_NO | wxICON_QUESTION ); if ( result == wxYES ) { wxGetApp().GetFrame()->NewProjectDialog(); } } if ( !m_Project ) // they failed to create a new project above { return; } if ( !path.IsUnder( m_Project->a_Path.Get().Directory() ) ) { tstringstream error; error << TXT( "You can only add files that live below the project.\nYou must move the file you're trying to drag somewhere below the directory:\n " ) << m_Project->a_Path.Get().Directory().c_str(); wxMessageBox( error.str(), TXT( "Error Adding File" ), wxOK | wxICON_ERROR ); return; } if ( CaseInsensitiveCompareString( path.Extension().c_str(), TXT( "HeliumScene" ) ) == 0 ) { m_Project->AddPath( path ); return; } #ifdef ASSET_REFACTOR Asset::AssetClassPtr asset = Asset::AssetClass::Create( path ); if ( asset.ReferencesObject() ) { m_Project->AddPath( asset->GetSourcePath() ); } else #endif { // we could not create a known asset type for this file, ask if they'd like to add it anyway int32_t result = wxMessageBox( wxT( "You've dragged a type of file into the project that we don't know how to handle.\n\nThat's ok, we can still add the file to the project and it will get included with the game, you just won't be able to do much else with it.\n\nWould you still like to add the file to the project?" ), wxT( "Unknown File Type" ), wxYES_NO | wxICON_QUESTION ); if ( result == wxYES ) { m_Project->AddPath( path ); } } #pragma TODO( "Set the item we just added to be selected" ) }
EntityNode& EntityNode::Get( const Helium::Path& path, bool createIfNotExisting ) { MFnDagNode dagFn; try { M_IdClassTransform::iterator findItor = s_ClassTransformsMap.find( path.Hash() ); if( findItor != s_ClassTransformsMap.end() ) { return *findItor->second; } else if ( createIfNotExisting ) { // we couldn't find it, so create it and return the loaded art class Asset::AssetClassPtr assetClass = Asset::AssetClass::LoadAssetClass( path ); if ( assetClass.ReferencesObject() ) { tstring artFilePath = assetClass->GetPath().Get(); MObject classTransform = dagFn.create( EntityNode::s_TypeID, assetClass->GetShortName().c_str() ); dagFn.setDoNotWrite( true ); EntityNode* artClass = static_cast<EntityNode*>( dagFn.userNode() ); artClass->m_AssetPath = path; artClass->SetArtFilePath( artFilePath.c_str() ); s_ClassTransformsMap[ path.Hash() ] = artClass; artClass->LoadArt(); return *artClass; } } } catch (Helium::Exception& ) { if ( createIfNotExisting ) { MGlobal::displayError( MString("Unable to create EntityNode!") ); } } return EntityNode::Null; }
void ProjectPanel::OnDroppedFiles( const FileDroppedArgs& args ) { HELIUM_ASSERT( m_Project ); Asset::AssetClassPtr asset = Asset::AssetClass::Create( args.m_Path ); if ( asset.ReferencesObject() ) { if ( asset->GetSerializationPath().Exists() ) { ProjectFilePtr file = new ProjectFile(); asset->SetSerializationPath( asset->GetSerializationPath().GetRelativePath( m_Project->Path().Get() ) ); file->Path().Set( asset->GetSerializationPath().Get() ); m_Project->AddChild( file ); } } }
void Tracker::TrackEverything() { HELIUM_ASSERT( m_Project ); m_StopTracking = false; m_InitialIndexingCompleted = false; m_IndexingFailed = false; #pragma TODO("Create default tables/migrate db") std::set< Helium::Path > assetFiles; while ( !m_StopTracking ) { Log::Print( m_InitialIndexingCompleted ? Log::Levels::Verbose : Log::Levels::Default, m_InitialIndexingCompleted ? TXT("Tracker: Looking for new or updated files...\n") : TXT("Tracker: Finding asset files...\n" )); // find all the files in the project { SimpleTimer timer; Helium::Directory directory( m_Project->a_Path.Get().Directory() ); directory.GetFiles( assetFiles, true ); Log::Print( m_InitialIndexingCompleted ? Log::Levels::Verbose : Log::Levels::Default, TXT("Tracker: File reslover database lookup took %.2fms\n"), timer.Elapsed() ); } // for each file m_CurrentProgress = 0; m_Total = (uint32_t)assetFiles.size(); SimpleTimer timer; Log::Print( m_InitialIndexingCompleted ? Log::Levels::Verbose : Log::Levels::Default, TXT("Tracker: Scanning %d asset file(s) for changes...\n"), (uint32_t)assetFiles.size() ); for( std::set< Helium::Path >::const_iterator assetFileItr = assetFiles.begin(), assetFileItrEnd = assetFiles.end(); !m_StopTracking && assetFileItr != assetFileItrEnd; ++assetFileItr ) { Log::Listener listener ( ~Log::Streams::Error ); ++m_CurrentProgress; // see if the file has changed // insert/update the file: path, timestamp, etc... const Helium::Path& assetFilePath = (*assetFileItr); #pragma TODO( "Make a configurable list of places to ignore" ) // skip files in the meta directory if ( assetFilePath.IsUnder( m_Project->a_Path.Get().Directory() + TXT( ".Helium/" ) ) ) { continue; } // start transaction #pragma TODO("Start transaction") try { #pragma TODO("Select tracked from from db, delete db obj if the real file has changed more recently") if ( WildcardMatch( TXT( "Helium*" ), assetFilePath.Extension().c_str() ) ) { #ifdef ASSET_REFACTOR const Asset::AssetClassPtr assetClass = Asset::AssetClass::LoadAssetClass( assetFilePath ); if ( assetClass.ReferencesObject() ) { // get file's properties Helium::SearchableProperties fileProperties; assetClass->GatherSearchableProperties( &fileProperties ); for( std::multimap< tstring, tstring >::const_iterator filePropertiesItr = fileProperties.GetStringProperties().begin(), filePropertiesItrEnd = fileProperties.GetStringProperties().end(); filePropertiesItr != filePropertiesItrEnd; ++filePropertiesItr ) { //TrackedProperty TrackedProperty prop( *m_TrackerDB ); prop.mName = filePropertiesItr->first; prop.update(); assetTrackedFile.properties().link( prop, filePropertiesItr->second ); } // get file's dependencies std::set< Helium::Path > fileReferences; assetClass->GetFileReferences( fileReferences ); for( std::set< Helium::Path >::const_iterator fileRefsItr = fileReferences.begin(), fileRefsItrEnd = fileReferences.end(); fileRefsItr != fileRefsItrEnd; ++fileRefsItr ) { // see if the file has changed const Helium::Path& fileRefPath = (*fileRefsItr); TrackedFile fileRefTrackedFile( *m_TrackerDB ); fileRefTrackedFile.mPath = fileRefPath.Get(); fileRefTrackedFile.update(); assetTrackedFile.fileReferences().link( fileRefTrackedFile ); } } #endif } #pragma TODO("Clear broken flag in the tracked file object") } catch ( const Helium::Exception& e ) { Log::Error( TXT( "Exception in Tracker thread: %s" ), e.What() ); #pragma TODO("Set the broken flag in the tracked file object") } catch ( ... ) { Log::Error( TXT( "Unknown exception in Tracker thread." ) ); #pragma TODO("Rollback transaction") // the consequences could never be the same here, rethrow throw; } #pragma TODO("Update and commit object state") #if 0 // update LastModified assetTrackedFile.mPath = assetFilePath.GetRelativePath( m_Project->a_Path.Get() ).Get(); assetTrackedFile.mSize = (int32_t) assetFilePath.Size(); assetTrackedFile.mLastModified = litesql::DateTime( assetFilePath.ModifiedTime() ); assetTrackedFile.mToolsVersion = HELIUM_VERSION_NUMBER; assetTrackedFile.update(); // commit transaction m_TrackerDB->commit(); #endif } if ( m_StopTracking ) { uint32_t percentComplete = (uint32_t)(((float32_t)m_CurrentProgress/(float32_t)m_Total) * 100); Log::Print( m_InitialIndexingCompleted ? Log::Levels::Verbose : Log::Levels::Default, TXT("Tracker: Indexing (%d%% complete) pre-empted after %.2fm\n"), percentComplete, timer.Elapsed() / 1000.f / 60.f ); } else if ( !m_InitialIndexingCompleted ) { m_InitialIndexingCompleted = true; Log::Print( TXT("Tracker: Initial indexing completed in %.2fm\n"), timer.Elapsed() / 1000.f / 60.f ); } else { Log::Print( Log::Levels::Verbose, TXT("Tracker: Indexing updated in %.2fm\n") , timer.Elapsed() / 1000.f / 60.f ); } m_Total = 0; m_CurrentProgress = 0; //////////////////////////////// // Recurse if ( !m_StopTracking ) { // Sleep between runs and yield to other threads // The complex loop is to prevent Editor from hanging on exit (max hang will be "increments" seconds) SleepBetweenTracking( &m_StopTracking ); } } }