/// Perform shutdown of the Asset system. /// /// This releases all final references to objects and releases all allocated memory. This should be called during /// the shutdown process after all types have been unregistered as well as after calling AssetType::Shutdown(). /// /// @see AssetType::Shutdown() void Asset::Shutdown() { HELIUM_TRACE( TraceLevels::Info, TXT( "Shutting down Asset system.\n" ) ); #if !HELIUM_RELEASE size_t objectCountActual = sm_objects.GetUsedSize(); if( objectCountActual != 0 ) { HELIUM_TRACE( TraceLevels::Error, TXT( "%" ) PRIuSZ TXT( " asset(s) still referenced during shutdown!\n" ), objectCountActual ); size_t objectCount = sm_objects.GetSize(); for( size_t objectIndex = 0; objectIndex < objectCount; ++objectIndex ) { if( !sm_objects.IsElementValid( objectIndex ) ) { continue; } Asset* pObject = sm_objects[ objectIndex ]; if( !pObject ) { continue; } #if HELIUM_ENABLE_MEMORY_TRACKING Helium::RefCountProxy<Reflect::Object> *pProxy = pObject->GetRefCountProxy(); HELIUM_ASSERT(pProxy); HELIUM_TRACE( TraceLevels::Error, TXT( " - 0x%p: %s (%" ) PRIu16 TXT( " strong ref(s), %" ) PRIu16 TXT( " weak ref(s))\n" ), pProxy, ( pObject ? *pObject->GetPath().ToString() : TXT( "(cleared reference)" ) ), pProxy->GetStrongRefCount(), pProxy->GetWeakRefCount() ); #else HELIUM_TRACE( TraceLevels::Error, TXT( "- %s\n" ), *pObject->GetPath().ToString() ); #endif } } #endif // !HELIUM_RELEASE sm_objects.Clear(); sm_wpFirstTopLevelObject.Release(); delete sm_pNameInstanceIndexMap; sm_pNameInstanceIndexMap = NULL; delete sm_pEmptyNameInstanceIndexMap; sm_pEmptyNameInstanceIndexMap = NULL; delete sm_pEmptyInstanceIndexSet; sm_pEmptyInstanceIndexSet = NULL; sm_serializationBuffer.Clear(); }
unsigned int ProjectViewModel::GetChildren( const wxDataViewItem& item, wxDataViewItemArray& items ) const { int count = 0; Asset *pAsset = NULL; if (!item.IsOk()) { ForciblyFullyLoadedPackageManager::GetStaticInstance()->ForceFullyLoadRootPackages(); pAsset = Asset::GetFirstTopLevelAsset(); } else { Asset* pParentAsset = static_cast< Asset* >( item.GetID() ); if ( pParentAsset->IsPackage() ) { ForciblyFullyLoadedPackageManager::GetStaticInstance()->ForceFullyLoadPackage( pParentAsset->GetPath() ); } pAsset = pParentAsset->GetFirstChild(); } while (pAsset) { //if ( m_AssetsInTree.Insert( pAsset ).Second() ) { items.Add( wxDataViewItem( pAsset ) ); ++count; } pAsset = pAsset->GetNextSibling(); } return count; }
const FilePath *Helium::Asset::GetAssetFileSystemPath() { HELIUM_ASSERT( !m_path.IsEmpty() ); FilePath filePath; Asset *pSourceAsset = GetSourceAsset(); if (pSourceAsset) { Package *pPackage = Reflect::SafeCast<Package>( pSourceAsset->GetOwner() ); if ( pPackage ) { PackageLoader *pLoader = pPackage->GetLoader(); HELIUM_ASSERT( pLoader->HasAssetFileState() ); if ( pLoader ) { return &pLoader->GetAssetFileSystemPath( pSourceAsset->GetPath() ); } } } return NULL; }
/// Update resource precaching for the given object load request. /// /// @param[in] pRequest Load request to update. /// /// @return True if resource precaching still requires processing, false if not. bool AssetLoader::TickPrecache( LoadRequest* pRequest ) { HELIUM_ASSERT( pRequest ); HELIUM_ASSERT( !( pRequest->stateFlags & LOAD_FLAG_LOADED ) ); Asset* pObject = pRequest->spObject; if( pObject ) { // TODO: SHouldn't this be in the linking phase? if ( !pRequest->resolver.TryFinishPrecachingDependencies() ) { return false; } pRequest->resolver.Clear(); // Perform any pre-precaching work (note that we don't precache anything for the default template object for // a given type). OnPrecacheReady( pObject, pRequest->pPackageLoader ); if( !pObject->GetAnyFlagSet( Asset::FLAG_BROKEN ) && !pObject->IsDefaultTemplate() && pObject->NeedsPrecacheResourceData() ) { if( !( pRequest->stateFlags & LOAD_FLAG_PRECACHE_STARTED ) ) { if( !pObject->BeginPrecacheResourceData() ) { HELIUM_TRACE( TraceLevels::Error, TXT( "AssetLoader: Failed to begin precaching object \"%s\".\n" ), *pObject->GetPath().ToString() ); pObject->SetFlags( Asset::FLAG_PRECACHED | Asset::FLAG_BROKEN ); AtomicOrRelease( pRequest->stateFlags, LOAD_FLAG_PRECACHED | LOAD_FLAG_ERROR ); return true; } AtomicOrRelease( pRequest->stateFlags, LOAD_FLAG_PRECACHE_STARTED ); } if( !pObject->TryFinishPrecacheResourceData() ) { return false; } } pObject->SetFlags( Asset::FLAG_PRECACHED ); } AtomicOrRelease( pRequest->stateFlags, LOAD_FLAG_PRECACHED ); return true; }
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; }
void AssetDatabase::HandleFileChanged(StringHash eventType, VariantMap& eventData) { using namespace FileChanged; const String& fullPath = eventData[P_FILENAME].GetString(); FileSystem* fs = GetSubsystem<FileSystem>(); String pathName, fileName, ext; SplitPath(fullPath, pathName, fileName, ext); // ignore changes in the Cache resource dir if (fullPath == GetCachePath() || pathName.StartsWith(GetCachePath())) return; // don't care about directories and asset file changes if (fs->DirExists(fullPath) || ext == ".asset") return; Asset* asset = GetAssetByPath(fullPath); if (!asset && fs->FileExists(fullPath)) { Scan(); return; } if (asset) { if(!fs->Exists(fullPath)) { DeleteAsset(asset); } else { if (asset->GetFileTimestamp() != fs->GetLastModifiedTime(asset->GetPath())) { asset->SetDirty(true); Scan(); } } } }
uint64_t Helium::Asset::GetAssetFileTimeStamp() { HELIUM_ASSERT( !m_path.IsEmpty() ); uint64_t timestamp = 0; Asset *pSourceAsset = GetSourceAsset(); if (pSourceAsset) { Package *pPackage = Reflect::SafeCast<Package>( pSourceAsset->GetOwner() ); if ( pPackage ) { PackageLoader *pLoader = pPackage->GetLoader(); HELIUM_ASSERT( pLoader->HasAssetFileState() ); if ( pLoader ) { pLoader->GetAssetFileSystemTimestamp( pSourceAsset->GetPath() ); } } } return timestamp; }
void ProjectViewModel::GetValue( wxVariant& variant, const wxDataViewItem& item, unsigned int column ) const { if ( !item.IsOk() || ( column >= m_ColumnLookupTable.size() ) ) { return; } Asset *node = static_cast< Asset* >( item.GetID() ); if ( !node ) { return; } switch( m_ColumnLookupTable.at( column ) ) { default: break; case ProjectModelColumns::Name: { uint32_t docStatus = DocumentStatus::Default; // node->GetDocumentStatus(); String assetString( *node->GetName() ); wxString name = *assetString; if ( HasFlags<uint32_t>( docStatus, DocumentStatus::Changed ) ) { name = wxString( TXT( '*' ) ) + name; } wxBitmap bitmap = wxArtProvider::GetBitmap( GetArtIDFromPath( node->GetPath() ), wxART_OTHER, wxSize(16, 16) ); if ( docStatus > 0 ) { wxImage image = bitmap.ConvertToImage(); HELIUM_ASSERT( image.Ok() ); int overlayWidth = image.GetWidth() / 2; int overlayHeight = image.GetHeight() / 2; wxImage overlayImage; if ( HasFlags<uint32_t>( docStatus, DocumentStatus::Saving ) ) { overlayImage = wxArtProvider::GetBitmap( ArtIDs::Status::Busy, wxART_OTHER, wxSize( overlayWidth, overlayHeight ) ).ConvertToImage(); HELIUM_ASSERT( overlayImage.Ok() ); } else if ( HasFlags<uint32_t>( docStatus, DocumentStatus::Loading ) ) { overlayImage = wxArtProvider::GetBitmap( ArtIDs::Status::Busy, wxART_OTHER, wxSize( overlayWidth, overlayHeight ) ).ConvertToImage(); HELIUM_ASSERT( overlayImage.Ok() ); } else if ( HasFlags<uint32_t>( docStatus, DocumentStatus::Changed ) ) { overlayImage = wxArtProvider::GetBitmap( ArtIDs::Actions::Edit, wxART_OTHER, wxSize( overlayWidth, overlayHeight ) ).ConvertToImage(); HELIUM_ASSERT( overlayImage.Ok() ); } if ( overlayImage.Ok() ) { if ( overlayImage.GetWidth() != overlayWidth || overlayImage.GetHeight() != overlayHeight ) { overlayImage.Rescale( overlayWidth, overlayHeight ); } int x = 0; int y = 0; IconArtFile::CalculatePlacement( image, overlayImage, OverlayQuadrants::BottomRight, x, y ); image.Paste( overlayImage, x, y ); } bitmap = wxBitmap( image ); } wxIcon icon; icon.CopyFromBitmap( bitmap ); variant << wxDataViewIconText( name, icon ); } break; //case ProjectModelColumns::Icon: // { // int32_t imageID = GlobalFileIconsTable().GetIconIDFromPath( node->GetPath() ); // wxVariant bitmapVariant; // bitmapVariant. // variant = GlobalFileIconsTable().GetSmallImageList()->GetBitmap( imageID ); // } // break; case ProjectModelColumns::Details: { variant = std::string( TXT( "" ) ); } break; case ProjectModelColumns::FileSize: { variant = std::string( TXT( "" ) ); } break; case ProjectModelColumns::Type: { const AssetType *pType = node->GetAssetType(); HELIUM_ASSERT( pType ); variant = std::string( *pType->GetName() ); } break; } }
/// @copydoc PackageLoader::BeginLoadObject() size_t LoosePackageLoader::BeginLoadObject( AssetPath path, Reflect::ObjectResolver *pResolver, bool forceReload ) { HELIUM_TRACE( TraceLevels::Info, TXT(" LoosePackageLoader::BeginLoadObject - Loading path %s\n"), *path.ToString() ); HELIUM_TRACE( TraceLevels::Debug, TXT( "LoosePackageLoader::BeginLoadObject: Beginning load for path \"%s\".\n"), *path.ToString()); HELIUM_TRACE( TraceLevels::Debug, TXT( "LoosePackageLoader::BeginLoadObject: Beginning load for path \"%s\". pResolver = %x\n"), *path.ToString(), pResolver); // Make sure preloading has completed. HELIUM_ASSERT( m_preloadedCounter != 0 ); if( !m_preloadedCounter ) { return Invalid< size_t >(); } // If this package is requested, simply provide the (already loaded) package instance. if( path == m_packagePath ) { LoadRequest* pRequest = m_loadRequestPool.Allocate(); HELIUM_ASSERT( pRequest ); HELIUM_ASSERT( m_spPackage ); pRequest->spObject = m_spPackage.Ptr(); SetInvalid( pRequest->index ); HELIUM_ASSERT( !pRequest->spType ); HELIUM_ASSERT( !pRequest->spTemplate ); HELIUM_ASSERT( !pRequest->spOwner ); SetInvalid( pRequest->templateLoadId ); SetInvalid( pRequest->ownerLoadId ); SetInvalid( pRequest->persistentResourceDataLoadId ); pRequest->pCachedObjectDataBuffer = NULL; pRequest->cachedObjectDataBufferSize = 0; SetInvalid( pRequest->asyncFileLoadId ); pRequest->pAsyncFileLoadBuffer = NULL; pRequest->asyncFileLoadBufferSize = 0; pRequest->pResolver = NULL; pRequest->forceReload = forceReload; pRequest->flags = LOAD_FLAG_PRELOADED; size_t requestId = m_loadRequests.Add( pRequest ); return requestId; } size_t objectIndex = FindObjectByPath( path ); size_t objectCount = GetObjectCount(); if( objectIndex >= objectCount ) { HELIUM_TRACE( TraceLevels::Error, TXT( "LoosePackageLoader::BeginLoadObject(): Failed to locate \"%s\" for loading. Verify the file exists.\n" ), *path.ToString() ); return Invalid< size_t >(); } SerializedObjectData& rObjectData = m_objects[ objectIndex ]; // Verify that the metadata was read successfully if( !rObjectData.bMetadataGood ) { HELIUM_TRACE( TraceLevels::Error, TXT( "LoosePackageLoader::BeginLoadObject(): Failed to read metadata for object \"%s\" during PackagePreload. Search log for parsing errors.\n" ), *path.ToString() ); return Invalid< size_t >(); } // Locate the type object. HELIUM_ASSERT( !rObjectData.typeName.IsEmpty() ); AssetType* pType = AssetType::Find( rObjectData.typeName ); if( !pType ) { HELIUM_TRACE( TraceLevels::Error, TXT( "LoosePackageLoader::BeginLoadObject(): Failed to locate type \"%s\" for loading object \"%s\".\n" ), *rObjectData.typeName, *path.ToString() ); HELIUM_TRACE( TraceLevels::Info, TXT( "Current registered types:\n" ) ); for ( AssetType::ConstIterator iter = AssetType::GetTypeBegin(); iter != AssetType::GetTypeEnd(); ++iter) { HELIUM_TRACE( TraceLevels::Info, TXT( " - %s\n" ), *iter->GetName() ); } return Invalid< size_t >(); } #ifndef NDEBUG size_t loadRequestSize = m_loadRequests.GetSize(); for( size_t loadRequestIndex = 0; loadRequestIndex < loadRequestSize; ++loadRequestIndex ) { if( !m_loadRequests.IsElementValid( loadRequestIndex ) ) { continue; } LoadRequest* pRequest = m_loadRequests[ loadRequestIndex ]; HELIUM_ASSERT( pRequest ); HELIUM_ASSERT( pRequest->index != objectIndex ); if( pRequest->index == objectIndex ) { return Invalid< size_t >(); } } #endif LoadRequest* pRequest = m_loadRequestPool.Allocate(); HELIUM_ASSERT( pRequest ); HELIUM_ASSERT( !pRequest->spObject ); pRequest->index = objectIndex; pRequest->spType = pType; HELIUM_ASSERT( !pRequest->spTemplate ); HELIUM_ASSERT( !pRequest->spOwner ); SetInvalid( pRequest->templateLoadId ); SetInvalid( pRequest->ownerLoadId ); SetInvalid( pRequest->persistentResourceDataLoadId ); pRequest->pCachedObjectDataBuffer = NULL; pRequest->cachedObjectDataBufferSize = 0; SetInvalid( pRequest->asyncFileLoadId ); pRequest->pAsyncFileLoadBuffer = NULL; pRequest->asyncFileLoadBufferSize = 0; pRequest->pResolver = pResolver; pRequest->forceReload = forceReload; pRequest->flags = 0; // If a fully-loaded object already exists with the same name, do not attempt to re-load the object (just mark // the request as complete). if ( !forceReload ) { pRequest->spObject = Asset::FindObject( path ); } Asset* pObject = pRequest->spObject; if( pObject && pObject->IsFullyLoaded() ) { pRequest->flags = LOAD_FLAG_PRELOADED; } else { HELIUM_ASSERT( !pObject || !pObject->GetAnyFlagSet( Asset::FLAG_LOADED | Asset::FLAG_LINKED ) ); // Begin loading the template and owner objects. Note that there isn't much reason to check for failure // until we tick this request, as we need to make sure any other load requests for the template/owner that // did succeed are properly synced anyway. AssetLoader* pAssetLoader = AssetLoader::GetStaticInstance(); HELIUM_ASSERT( pAssetLoader ); if( rObjectData.templatePath.IsEmpty() ) { // Make sure the template is fully loaded. Asset* pTemplate = pType->GetTemplate(); rObjectData.templatePath = pTemplate->GetPath(); if( pTemplate->IsFullyLoaded() ) { pRequest->spTemplate = pTemplate; } else { pRequest->templateLoadId = pAssetLoader->BeginLoadObject( rObjectData.templatePath ); } } else { pRequest->templateLoadId = pAssetLoader->BeginLoadObject( rObjectData.templatePath ); } AssetPath ownerPath = path.GetParent(); if( ownerPath == m_packagePath ) { // Easy check: if the owner is this package (which is likely), we don't need to load it. pRequest->spOwner = m_spPackage.Ptr(); } else if( !ownerPath.IsEmpty() ) { pRequest->ownerLoadId = pAssetLoader->BeginLoadObject( ownerPath ); } } size_t requestId = m_loadRequests.Add( pRequest ); return requestId; }
bool ModelImporter::ImportAnimations() { if (!animationInfo_.Size()) { if (!ImportAnimation(asset_->GetPath(), "RootAnim")) return false; } // embedded animations for (unsigned i = 0; i < animationInfo_.Size(); i++) { const SharedPtr<AnimationImportInfo>& info = animationInfo_[i]; if (!ImportAnimation(asset_->GetPath(), info->GetName(), info->GetStartTime(), info->GetEndTime())) return false; } // add @ animations FileSystem* fs = GetSubsystem<FileSystem>(); String pathName, fileName, ext; SplitPath(asset_->GetPath(), pathName, fileName, ext); Vector<String> results; fs->ScanDir(results, pathName, ext, SCAN_FILES, false); for (unsigned i = 0; i < results.Size(); i++) { const String& result = results[i]; if (result.Contains("@")) { Vector<String> components = GetFileName(result).Split('@'); if (components.Size() == 2 && components[1].Length() && components[0] == fileName) { String animationName = components[1]; AssetDatabase* db = GetSubsystem<AssetDatabase>(); Asset* asset = db->GetAssetByPath(pathName + result); assert(asset); assert(asset->GetImporter()->GetType() == ModelImporter::GetTypeStatic()); ModelImporter* importer = (ModelImporter*) asset->GetImporter(); if (!importer->animationInfo_.Size()) { if (!ImportAnimation(asset->GetPath(), animationName)) return false; } else { // embedded animations for (unsigned i = 0; i < importer->animationInfo_.Size(); i++) { const SharedPtr<AnimationImportInfo>& info = importer->animationInfo_[i]; if (!ImportAnimation(asset->GetPath(), info->GetName(), info->GetStartTime(), info->GetEndTime())) return false; } } } } } return true; }
/// @copydoc PackageLoader::TryFinishLoadObject() bool CachePackageLoader::TryFinishLoadObject( size_t requestId, AssetPtr& rspObject ) { HELIUM_ASSERT( requestId < m_loadRequests.GetSize() ); HELIUM_ASSERT( m_loadRequests.IsElementValid( requestId ) ); LoadRequest* pRequest = m_loadRequests[ requestId ]; HELIUM_ASSERT( pRequest ); if( !( pRequest->flags & LOAD_FLAG_PRELOADED ) ) { return false; } // Sync on template and owner dependencies. AssetLoader* pAssetLoader = AssetLoader::GetInstance(); HELIUM_ASSERT( pAssetLoader ); if( IsValid( pRequest->ownerLoadIndex ) ) { size_t linkLoadId = pRequest->ownerLoadIndex; if( IsValid( linkLoadId ) && !pAssetLoader->TryFinishLoad( linkLoadId, pRequest->spOwner ) ) { return false; } SetInvalid( pRequest->ownerLoadIndex ); } rspObject = pRequest->spObject; Asset* pObject = rspObject; if( pObject && ( pRequest->flags & LOAD_FLAG_ERROR ) ) { pObject->SetFlags( Asset::FLAG_BROKEN ); } if ( pObject->IsPackage() ) { Package *pPackage = Reflect::AssertCast<Package>( pObject ); pPackage->SetLoader( this ); } pRequest->spObject.Release(); HELIUM_ASSERT( IsInvalid( pRequest->asyncLoadId ) ); HELIUM_ASSERT( !pRequest->pAsyncLoadBuffer ); //pRequest->spTemplate.Release(); pRequest->spOwner.Release(); HELIUM_ASSERT( IsInvalid( pRequest->ownerLoadIndex ) ); //HELIUM_ASSERT( IsInvalid( pRequest->templateLoadIndex ) ); HELIUM_ASSERT( pObject || pRequest->pEntry ); HELIUM_TRACE( TraceLevels::Debug, "CachePackageLoader::TryFinishLoadObject(): Load request for \"%s\" (ID: %" PRIuSZ ") synced.\n", *( pObject ? pObject->GetPath() : pRequest->pEntry->path ).ToString(), requestId ); m_loadRequests.Remove( requestId ); m_loadRequestPool.Release( pRequest ); return true; }
/// Modify the name, owner, or instance index of this object. /// /// @param[in] rParameters Object rename parameters. /// /// @return True if this object was renamed successfully, false if not. /// /// @see GetName(), GetOwner(), GetInstanceIndex() bool Asset::Rename( const RenameParameters& rParameters ) { Name name = rParameters.name; Asset* pOwner = rParameters.spOwner; uint32_t instanceIndex = rParameters.instanceIndex; HELIUM_TRACE( TraceLevels::Debug, TXT("Asset::Rename(): Renaming object \"%s\" to \"%s\" (Old Owner: \"%s\". New Owner: \"%s\".)\n"), *m_name, *rParameters.name, m_spOwner.ReferencesObject() ? *m_spOwner->GetPath().ToString() : TXT("[none]"), rParameters.spOwner.ReferencesObject() ? *rParameters.spOwner->GetPath().ToString() : TXT("[none]")); // Only allow setting an empty name if no owner or instance index are given and this object has no children. if( name.IsEmpty() ) { HELIUM_ASSERT( !pOwner ); HELIUM_ASSERT( IsInvalid( instanceIndex ) ); if( pOwner || IsValid( instanceIndex ) ) { HELIUM_TRACE( TraceLevels::Error, ( TXT( "Asset::Rename(): Objects cannot have name information cleared if being assigned an " ) TXT( "owner or instance index.\n" ) ) ); return false; } HELIUM_ASSERT( !m_wpFirstChild ); if( m_wpFirstChild ) { HELIUM_TRACE( TraceLevels::Error, TXT( "Asset::Rename(): Cannot clear name information for objects with children.\n" ) ); return false; } } // Don't allow setting the owner to ourself. if( pOwner == this ) { HELIUM_TRACE( TraceLevels::Error, TXT( "Asset::Rename(): Cannot set the owner of an object to itself.\n" ) ); return false; } // Don't allow setting the owner to an object with no name information. if( pOwner && pOwner->m_name.IsEmpty() ) { HELIUM_TRACE( TraceLevels::Error, TXT( "Asset::Rename(): Cannot set the owner of an object to an object with no path information.\n" ) ); return false; } if( IsPackage() ) { // Don't allow package objects to be children of non-package objects. if( pOwner && !pOwner->IsPackage() ) { HELIUM_TRACE( TraceLevels::Error, TXT( "Asset::Rename(): Cannot set a non-package as the owner of a package.\n" ) ); return false; } // Don't allow instance indexing for packages. if( IsValid( instanceIndex ) ) { HELIUM_TRACE( TraceLevels::Error, TXT( "Asset::Rename(): Instance indexing not supported for packages.\n" ) ); return false; } } // Don't need to do anything if the name, owner, and instance index are not changing. if( name == m_name && pOwner == m_spOwner && ( instanceIndex == m_instanceIndex || ( instanceIndex == INSTANCE_INDEX_AUTO && IsValid( m_instanceIndex ) ) ) ) { return true; } // Hold onto a reference to the current owner until we return from this function. This is done in case this object // has the last strong reference to it, in which case we would encounter a deadlock if clearing its reference while // we still have a write lock on the object list (object destruction also requires acquiring a write lock). AssetPtr spOldOwner = m_spOwner; { // Acquire a write lock on the object list to prevent objects from being added and removed as well as keep // objects from being renamed while this object is being renamed. ScopeWriteLock scopeLock( sm_objectListLock ); // Get the list of children belonging to the new owner. AssetWPtr& rwpOwnerFirstChild = ( pOwner ? pOwner->m_wpFirstChild : sm_wpFirstTopLevelObject ); // Don't check for name clashes if we're clearing the object path name information. if( !name.IsEmpty() ) { // Resolve name clashes either through the instance index lookup map (if an instance index will be assigned) // or through a child object search (if no instance index will be used). if( IsValid( instanceIndex ) ) { // Get the instance index map for the requested object name. ChildNameInstanceIndexMap& rNameInstanceIndexMap = GetNameInstanceIndexMap(); HELIUM_ASSERT( sm_pEmptyNameInstanceIndexMap ); HELIUM_ASSERT( sm_pEmptyInstanceIndexSet ); sm_pEmptyNameInstanceIndexMap->First() = ( pOwner ? pOwner->GetPath() : AssetPath( NULL_NAME ) ); sm_pEmptyInstanceIndexSet->First() = name; ChildNameInstanceIndexMap::Accessor childNameMapAccessor; rNameInstanceIndexMap.Insert( childNameMapAccessor, *sm_pEmptyNameInstanceIndexMap ); NameInstanceIndexMap::Accessor indexSetAccessor; childNameMapAccessor->Second().Insert( indexSetAccessor, *sm_pEmptyInstanceIndexSet ); InstanceIndexSet& rIndexSet = indexSetAccessor->Second(); InstanceIndexSet::ConstAccessor indexAccessor; if( instanceIndex == INSTANCE_INDEX_AUTO ) { // Pick an unused instance index. instanceIndex = 0; while( !rIndexSet.Insert( indexAccessor, instanceIndex ) ) { ++instanceIndex; HELIUM_ASSERT( instanceIndex < INSTANCE_INDEX_AUTO ); } } else { // Attempt to acquire the specified instance index. if( !rIndexSet.Insert( indexAccessor, instanceIndex ) ) { HELIUM_TRACE( TraceLevels::Error, ( TXT( "Asset::Rename(): Object already exists with the specified owner (%s), name " ) TXT( "(%s), and instance index (%" ) PRIu32 ").\n" ), ( pOwner ? *pOwner->GetPath().ToString() : TXT( "none" ) ), *name, instanceIndex ); return false; } } } else { // Check each child of the new owner for a name clash. for( Asset* pChild = rwpOwnerFirstChild; pChild != NULL; pChild = pChild->m_wpNextSibling ) { if( pChild->m_name == name && pChild->m_instanceIndex == instanceIndex ) { HELIUM_TRACE( TraceLevels::Error, ( TXT( "Asset::Rename(): Object already exists with the specified owner (%s) and " ) TXT( "name (%s).\n" ) ), ( pOwner ? *pOwner->GetPath().ToString() : TXT( "none" ) ), *name ); return false; } } } } // Remove any old instance index tracking for the old path name. if( IsValid( m_instanceIndex ) ) { AssetPath ownerPath = ( spOldOwner ? spOldOwner->GetPath() : AssetPath( NULL_NAME ) ); ChildNameInstanceIndexMap& rNameInstanceIndexMap = GetNameInstanceIndexMap(); ChildNameInstanceIndexMap::Accessor childMapAccessor; HELIUM_VERIFY( rNameInstanceIndexMap.Find( childMapAccessor, ownerPath ) ); NameInstanceIndexMap& rNameMap = childMapAccessor->Second(); NameInstanceIndexMap::Accessor nameMapAccessor; HELIUM_VERIFY( rNameMap.Find( nameMapAccessor, m_name ) ); InstanceIndexSet& rIndexSet = nameMapAccessor->Second(); HELIUM_VERIFY( rIndexSet.Remove( m_instanceIndex ) ); /* if( rIndexSet.IsEmpty() ) { HELIUM_VERIFY( rNameMap.Remove( nameMapAccessor ) ); if( rNameMap.IsEmpty() ) { HELIUM_VERIFY( rNameInstanceIndexMap.Remove( childMapAccessor ) ); } } */ } // If the owner of this object is changing, remove this object from its old owner's list and add it to the new // owner. if( spOldOwner.Get() != pOwner || ( m_name.IsEmpty() ? !name.IsEmpty() : name.IsEmpty() ) ) { // Object should not be in any child object lists if its name is empty. if( !m_name.IsEmpty() ) { AssetWPtr& rwpOldOwnerFirstChild = ( spOldOwner ? spOldOwner->m_wpFirstChild : sm_wpFirstTopLevelObject ); Asset* pPreviousChild = NULL; Asset* pChild = rwpOldOwnerFirstChild; while( pChild ) { if( pChild == this ) { ( pPreviousChild ? pPreviousChild->m_wpNextSibling : rwpOldOwnerFirstChild ) = m_wpNextSibling; m_wpNextSibling.Release(); break; } pPreviousChild = pChild; pChild = pChild->m_wpNextSibling; } } // If you assert here, it's possible that sm_wpFirstTopLevelObject is null. This can happen if an asset is destroyed // after the asset system is shut down HELIUM_ASSERT( !m_wpNextSibling ); // Only store the object in a child object list if it is being given a valid name. if( !name.IsEmpty() ) { m_wpNextSibling = rwpOwnerFirstChild; rwpOwnerFirstChild = this; } } // Set the new path name. m_name = name; m_spOwner = pOwner; m_instanceIndex = instanceIndex; // Update path information for this object and its children. UpdatePath(); } return true; }
void ProjectPanel::OnLoadForEdit( wxCommandEvent& event ) { wxDataViewItemArray selection; int numSelected = m_DataViewCtrl->GetSelections( selection ); for (int i = 0; i < numSelected; ++i) { Asset *pAsset = static_cast<Asset *>( selection[i].GetID() ); if (pAsset && pAsset->IsPackage()) { ForciblyFullyLoadedPackageManager::GetStaticInstance()->ForceFullyLoadPackage(pAsset->GetPath()); } } }
void SceneView3D::HandleDragEnded(StringHash eventType, VariantMap& eventData) { using namespace DragEnded; UIDragObject* dragObject = static_cast<UIDragObject*>(eventData[P_DRAGOBJECT].GetPtr()); if (dragNode_.NotNull()) { VariantMap neventData; neventData[EditorActiveNodeChange::P_NODE] = dragNode_; SendEvent(E_EDITORACTIVENODECHANGE, neventData); } if (dragObject && dragObject->GetObject()->GetType() == ToolCore::Asset::GetTypeStatic()) { Asset* asset = (ToolCore::Asset*) dragObject->GetObject(); if (asset->GetImporterTypeName() == "MaterialImporter") { Material* material = GetSubsystem<ResourceCache>()->GetResource<Material>(asset->GetPath()); if (material) { material = material; Ray camRay = GetCameraRay(); PODVector<RayQueryResult> result; RayOctreeQuery query(result, camRay, RAY_TRIANGLE, camera_->GetFarClip(), DRAWABLE_GEOMETRY, 0x7fffffff); octree_->RaycastSingle(query); if (query.result_.Size()) { const RayQueryResult& r = result[0]; if (r.drawable_ && (r.drawable_->GetType() == StaticModel::GetTypeStatic() || r.drawable_->GetType() == AnimatedModel::GetTypeStatic())) { ((StaticModel*)r.drawable_)->SetMaterial(material); } } } } } dragAssetGUID_ = ""; dragNode_ = 0; }
void SceneView3D::HandleDragEnterWidget(StringHash eventType, VariantMap& eventData) { using namespace DragEnterWidget; UIWidget* widget = static_cast<UIWidget*>(eventData[P_WIDGET].GetPtr()); if (widget != this) return; UIDragObject* dragObject = static_cast<UIDragObject*>(eventData[P_DRAGOBJECT].GetPtr()); Object* object = dragObject->GetObject(); if (!object) return; if (object->GetType() == Asset::GetTypeStatic()) { Asset* asset = (Asset*) object; AssetImporter* importer = asset->GetImporter(); if (!importer) return; StringHash importerType = importer->GetType(); if (importerType == PrefabImporter::GetTypeStatic()) { dragNode_ = scene_->CreateChild(asset->GetName()); PrefabComponent* pc = dragNode_->CreateComponent<PrefabComponent>(); pc->SetPrefabGUID(asset->GetGUID()); } else if (importerType == ModelImporter::GetTypeNameStatic()) { dragNode_ = scene_->CreateChild(); SharedPtr<File> file(new File(context_, asset->GetCachePath())); SharedPtr<XMLFile> xml(new XMLFile(context_)); if (!xml->Load(*file)) return; dragNode_->LoadXML(xml->GetRoot()); dragNode_->SetName(asset->GetName()); } else if (importerType == SpriterImporter::GetTypeNameStatic()) { AnimationSet2D* animationSet = GetSubsystem<ResourceCache>()->GetResource<AnimationSet2D>(asset->GetPath()); String animationName; if (animationSet && animationSet->GetNumAnimations()) { animationName = animationSet->GetAnimation(0)->GetName(); } dragNode_ = scene_->CreateChild(asset->GetName()); AnimatedSprite2D* sprite = dragNode_->CreateComponent<AnimatedSprite2D>(); if (!animationName.Length()) sprite->SetAnimationSet(animationSet); else sprite->SetAnimation(animationSet, animationName); } else if (importerType == TextureImporter::GetTypeNameStatic()) { dragNode_ = scene_->CreateChild(asset->GetName()); Sprite2D* spriteGraphic = GetSubsystem<ResourceCache>()->GetResource<Sprite2D>(asset->GetPath()); StaticSprite2D* sprite = dragNode_->CreateComponent<StaticSprite2D>(); sprite->SetSprite(spriteGraphic); } if (dragNode_.NotNull()) { Input* input = GetSubsystem<Input>(); IntVector2 pos = input->GetMousePosition(); UpdateDragNode(pos.x_, pos.y_); } //LOGINFOF("Dropped %s : %s on SceneView3D", asset->GetPath().CString(), asset->GetGUID().CString()); } }