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; }
bool ProjectViewModel::GetAttr( const wxDataViewItem& item, unsigned int column, wxDataViewItemAttr& attr ) const { if ( !item.IsOk() ) { return false; } Asset *node = static_cast< Asset* >( item.GetID() ); HELIUM_ASSERT( node ); // bold the entry if the node is active attr.SetBold( node->IsPackage() ); if ( node->GetAllFlagsSet( Asset::FLAG_EDITOR_FORCIBLY_LOADED ) ) { attr.SetColour( *wxBLACK ); } else { attr.SetColour( *wxLIGHT_GREY ); } // italicize the entry if it is modified attr.SetItalic( node->GetAllFlagsSet( Asset::FLAG_CHANGED_SINCE_LOADED ) ); if ( node->GetAllFlagsSet( Asset::FLAG_CHANGED_SINCE_LOADED ) ) { attr.SetColour( *wxRED ); } 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()); } } }
/// @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; }