/* ----------------------------------------------------------------------------- GSFramework Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. ----------------------------------------------------------------------------- */ #include "tools/resource_explorer.h" #include "metafile/nml.h" #include "platform.h" #include "filesystem/filesystem.h" using namespace GS::Resource; using namespace GS::NML; using GS::String; //------------------------------------------------------------------------------ DependencyRule scene3d_dependency_rules[] = { // Instances { "Items/*Instance/Template", "Scene" }, // Terrains { "Items/*MTerrain/Terrain/Blendmap", "Texture" }, { "Items/*MTerrain/Terrain/Blendmap", "Shader" }, { "Items/*MTerrain/Terrain/MaterialName", "Material" }, { "Items/*MTerrain/Terrain/Heightmap/Data", "Data" }, { "Items/*MTerrain/Terrain/Layers/*Layer/Diffuse", "Texture" }, { "Items/*MTerrain/Terrain/Layers/*Layer/Normal", "Texture" }, { "Items/*MTerrain/Terrain/Layers/*Layer/Specular", "Texture" }, { "Items/*MTerrain/Terrain/Layers/*Layer/Self", "Texture" }, // Lights { "Items/*MLight/Light/ProjectionMap", "Texture" }, // Objects { "Items/*MObject/Object/Geometry", "Geometry" }, // All items { "Items/*/MItem/ScriptedObject/*ScriptUnit/Script", "Script" }, // legacy { "Items/*/MItem/ScriptedObject/*ScriptUnit/ScriptPath", "Script" }, { "Items/*/MItem/PhysicItem/Shapes/*PhysicShape/Mesh", "Geometry" }, // Scene { "ScriptedObject/*ScriptUnit/Script", "Script" }, // legacy { "ScriptedObject/*ScriptUnit/ScriptPath", "Script" }, { 0, 0 } }; DependencyRule geometry_dependency_rules[] = { { "Materials/*MaterialRef", "Material" }, { "Materials/*MaterialRefEx/Name", "Material" }, { "LodProxy", "Geometry" }, { "ShadowProxy", "Geometry" }, { 0, 0 } }; DependencyRule material_dependency_rules[] = { { "*TextureStage/Texture", "Texture" }, { "Shader", "Shader" }, { 0, 0 } }; DependencyRule shader_tree_dependency_rules[] = { { "Map/*Entry/Param/Texture", "Texture" }, { 0, 0 } }; DependencyRule shader_dependency_rules[] = { { "Input/*Uniform/Texture", "Texture" }, { 0, 0 } }; //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ ExplorerRule resource_rules[] = { { "Scene3d", "Scene", scene3d_dependency_rules }, { "Geometry", "Geometry", geometry_dependency_rules }, { "Material", "Material", material_dependency_rules }, { "Shader Tree", "ShaderMap", shader_tree_dependency_rules }, { "Shader", "Shader", shader_dependency_rules }, { 0, 0 } }; //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ const char *Explorer::DependencyTag::GetName() const { return tag->GetString(); } void Explorer::DependencyTag::SetName(const char *n) { tag->SetString(n); } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ bool resource_filter(const Explorer::Resource *r, const char *name) { return r->name == name; } bool dependency_filter(const Explorer::Dependency *d, const char *name) { return !String::strccmp(d->GetName(), name); } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ const Explorer::Dependency *Explorer::Resource::FindDependency(const char *n) const { return ListFindEx(dependencies, dependency_filter, n); } bool Explorer::Resource::HasMissingDependencies() const { ListForeachPtr(Dependency *, dep, dependencies) if (dep->missing) return true; return false; } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ void Explorer::ExploreResourceRuleTags(const GS::StringList &tags, uint pos, Tag *tag, Resource *r, int depth) { if (pos == tags.GetCount()) // end of path { if (tag->GetString()) { String name = tag->GetString(); // if (!r->FindDependency(name)) { DependencyTag *dependency = new DependencyTag(tag); r->dependencies.Add(dependency); if (name.StartsWith("@sys/")) // engine generated resource dependency->missing = false; else if (name.StartsWith("@core/")) dependency->missing = !Platform::Get().io->Exists(name); // Assert dependency is found. else if (!name.IsAbsolutePath()) { // Check in project path. if (!project_path.IsEmpty()) { String _name = String::Format("%s/%s", project_path.c_str(), name.c_str()).CleanFilePath(); if ((dependency->missing = !Platform::Get().io->Exists(_name)) == false) name = _name; } // Check in core path if still missing. if (dependency->missing) if (!core_path.IsEmpty()) { String _name = String::Format("%s/%s", core_path.c_str(), name.c_str()).CleanFilePath(); if ((dependency->missing = !Platform::Get().io->Exists(_name)) == false) name = _name; } } ExploreResource(name, project_path, core_path, depth - 1); } } } else { const String &t = tags[pos]; if (t.StartsWith("*")) // iterate current tag { String match = t.Mid(1); NMLTagForeach(c, *tag) if (match.IsEmpty() || (c->name == match)) ExploreResourceRuleTags(tags, pos + 1, c, r, depth); } else { if (Tag *c = tag->GetTag(t)) // no tag means rule not met ExploreResourceRuleTags(tags, pos + 1, c, r, depth); } } } bool Explorer::ExploreResourceRule(ExplorerRule &rule, Resource *r, int depth) { Tag *tag = r->file->GetTag(rule.root); if (!tag) return false; r->type = rule.type; for (int n = 0; rule.rules[n].type; ++n) { // Split rule tags. StringList tags; String(rule.rules[n].path).Split("/", tags); ExploreResourceRuleTags(tags, 0, tag, r, depth); } return true; } Explorer::Resource *Explorer::ExploreResource(const char *name, const char *_project_path, const char *_core_path, int depth) { if (depth <= 0) return NULL; project_path = _project_path; core_path = _core_path; // Metafile. if (!Parser::IsMetafile(name)) return NULL; // Check if that resource has already been loaded. if (Resource *_r = ListFindEx(resources, resource_filter, name)) return _r; // Load file. AutoPtr r(new Resource(name, "Null")); r->file = Parser::Load(name); if (r->file.IsNull()) return NULL; // Explore resource. for (int n = 0; resource_rules[n].type; ++n) if (ExploreResourceRule(resource_rules[n], r, depth)) { resources.Add(r); return r.Detach(); } return NULL; } const Explorer::Resource *Explorer::FindResource(const char *name) const { return ListFindEx(resources, resource_filter, name); } void Explorer::Clear() { resources.Clear(); } //------------------------------------------------------------------------------