Browse Source

Resource dependency tracking for reloading resources. Currently implemented for ScriptFile.

Lasse Öörni 12 years ago
parent
commit
20e6dd0da6
3 changed files with 61 additions and 1 deletions
  1. 48 1
      Engine/Resource/ResourceCache.cpp
  2. 6 0
      Engine/Resource/ResourceCache.h
  3. 7 0
      Engine/Script/ScriptFile.cpp

+ 48 - 1
Engine/Resource/ResourceCache.cpp

@@ -598,6 +598,38 @@ void ResourceCache::StoreNameHash(const String& name)
         hashToName_[hash] = name;
 }
 
+void ResourceCache::StoreResourceDependency(Resource* resource, const String& dependency)
+{
+    Vector<WeakPtr<Resource> >& dependents = dependentResources_[StringHash(dependency)];
+    WeakPtr<Resource> resourceWeak(resource);
+    if (!dependents.Contains(resourceWeak))
+        dependents.Push(resourceWeak);
+}
+
+void ResourceCache::ResetDependencies(Resource* resource)
+{
+    WeakPtr<Resource> resourceWeak(resource);
+    
+    for (HashMap<StringHash, Vector<WeakPtr<Resource> > >::Iterator i = dependentResources_.Begin(); i !=
+        dependentResources_.End();)
+    {
+        Vector<WeakPtr<Resource> >& dependents = i->second_;
+        bool remove = false;
+        
+        if (dependents.Contains(resourceWeak))
+        {
+            dependents.Remove(resourceWeak);
+            if (dependents.Empty())
+                remove = true;
+        }
+        
+        if (remove)
+            i = dependentResources_.Erase(i);
+        else
+            ++i;
+    }
+}
+
 const SharedPtr<Resource>& ResourceCache::FindResource(ShortStringHash type, StringHash nameHash)
 {
     HashMap<ShortStringHash, ResourceGroup>::Iterator i = resourceGroups_.Find(type);
@@ -688,16 +720,31 @@ void ResourceCache::HandleBeginFrame(StringHash eventType, VariantMap& eventData
         String fileName;
         while (fileWatchers_[i]->GetNextChange(fileName))
         {
+            StringHash fileNameHash(fileName);
             // If the filename is a resource we keep track of, reload it
             for (HashMap<ShortStringHash, ResourceGroup>::Iterator j = resourceGroups_.Begin(); j != resourceGroups_.End(); ++j)
             {
-                HashMap<StringHash, SharedPtr<Resource> >::Iterator k = j->second_.resources_.Find(StringHash(fileName));
+                HashMap<StringHash, SharedPtr<Resource> >::Iterator k = j->second_.resources_.Find(fileNameHash);
                 if (k != j->second_.resources_.End())
                 {
                     LOGDEBUG("Reloading changed resource " + fileName);
                     ReloadResource(k->second_);
                 }
             }
+            // Check if this is a dependency resource, reload dependents
+            HashMap<StringHash, Vector<WeakPtr<Resource> > >::Iterator j = dependentResources_.Find(fileNameHash);
+            if (j != dependentResources_.End())
+            {
+                Vector<WeakPtr<Resource> >& dependents = j->second_;
+                for (unsigned k = 0; k < dependents.Size(); ++k)
+                {
+                    if (dependents[k])
+                    {
+                        LOGDEBUG("Reloading resource " + dependents[k]->GetName() + " depending on " + fileName);
+                        ReloadResource(dependents[k]);
+                    }
+                }
+            }
         }
     }
 }

+ 6 - 0
Engine/Resource/ResourceCache.h

@@ -132,6 +132,10 @@ public:
     String SanitateResourceName(const String& name) const;
     /// Store a hash-to-name mapping.
     void StoreNameHash(const String& name);
+    /// Store a dependency for a resource. If a dependency file changes, the resource will be reloaded.
+    void StoreResourceDependency(Resource* resource, const String& dependency);
+    /// Reset dependencies for a resource.
+    void ResetDependencies(Resource* resource);
     
 private:
     /// Find a resource.
@@ -153,6 +157,8 @@ private:
     Vector<SharedPtr<PackageFile> > packages_;
     /// Mapping of hashes to filenames.
     HashMap<StringHash, String> hashToName_;
+    /// Dependent resources.
+    HashMap<StringHash, Vector<WeakPtr<Resource> > > dependentResources_;
     /// Automatic resource reloading flag.
     bool autoReloadResources_;
 };

+ 7 - 0
Engine/Script/ScriptFile.cpp

@@ -101,6 +101,11 @@ bool ScriptFile::Load(Deserializer& source)
     // Map script module to script resource with userdata
     scriptModule_->SetUserData(this);
     
+    // Store include files as dependencies
+    ResourceCache* cache = GetSubsystem<ResourceCache>();
+    for (HashSet<String>::Iterator i = includeFiles_.Begin(); i != includeFiles_.End(); ++i)
+        cache->StoreResourceDependency(this, *i);
+    
     return true;
 }
 
@@ -527,6 +532,8 @@ void ScriptFile::ReleaseModule()
         scriptModule_ = 0;
         compiled_ = false;
         SetMemoryUse(0);
+        
+        GetSubsystem<ResourceCache>()->ResetDependencies(this);
     }
 }