236 lines
6.9 KiB
C++
236 lines
6.9 KiB
C++
/* -----------------------------------------------------------------------------
|
|
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 <Resource> 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();
|
|
}
|
|
//------------------------------------------------------------------------------
|