11#include "third_party/nlohmann/json.hpp"
52 std::vector<const PrefabBlueprint*>
results;
57 if (
pair.second.prefabType == type)
68 std::vector<std::string>
names;
99 SYSTEM_LOG <<
"+======================================================================+\\n";
101 SYSTEM_LOG <<
"|======================================================================|\n";
103 SYSTEM_LOG <<
"\\======================================================================+\n\n";
109 SYSTEM_LOG <<
"-> Scanning for .json files...\n";
139 <<
"(" <<
blueprint.components.size() <<
" components, "
146 SYSTEM_LOG <<
" x " << filepath <<
" (parse failed)";
156 SYSTEM_LOG <<
"+======================================================================+ \n";
158 SYSTEM_LOG <<
"|======================================================================| \n";
167 SYSTEM_LOG <<
"\\======================================================================+ \n\n";
173void PrefabScanner::ScanDirectoryRecursive_Windows(
const std::string& path, std::vector<std::string>&
outFiles)
192 std::string fullPath = path +
"\\" +
filename;
230 std::string fullPath = path +
"/" +
filename;
264 std::ifstream
file(filepath);
267 blueprint.errors.push_back(
"Failed to open file");
271 std::string
content((std::istreambuf_iterator<char>(
file)),
272 std::istreambuf_iterator<char>());
285 if (
j.contains(
"type"))
287 std::string
typeValue =
j[
"type"].get<std::string>();
293 else if (
j.contains(
"blueprintType"))
295 blueprint.prefabType =
j[
"blueprintType"].get<std::string>();
305 if (
j.contains(
"schema_version"))
310 if (
j.contains(
"description"))
312 blueprint.description =
j[
"description"].get<std::string>();
315 if (
j.contains(
"name"))
317 blueprint.prefabName =
j[
"name"].get<std::string>();
321 if (
j.contains(
"data") &&
j[
"data"].is_object())
323 json dataJson =
j[
"data"];
326 if (dataJson.contains(
"prefabName"))
328 blueprint.prefabName = dataJson[
"prefabName"].get<std::string>();
332 if (dataJson.contains(
"components") && dataJson[
"components"].is_array())
343 catch (
const std::exception&
e)
345 blueprint.errors.push_back(std::string(
"Component parse error: ") +
e.what());
356 catch (
const std::exception&
e)
358 blueprint.errors.push_back(std::string(
"JSON parse error: ") +
e.what());
377 if (
lower.find(
"identity") != std::string::npos)
return "Identity";
378 if (
lower.find(
"position") != std::string::npos)
return "Position";
379 if (
lower.find(
"sprite") != std::string::npos ||
lower.find(
"visual") != std::string::npos)
return "VisualSprite";
380 if (
lower.find(
"boundingbox") != std::string::npos ||
lower.find(
"collision") != std::string::npos)
return "BoundingBox";
381 if (
lower.find(
"movement") != std::string::npos)
return "Movement";
382 if (
lower.find(
"physics") != std::string::npos)
return "PhysicsBody";
383 if (
lower.find(
"health") != std::string::npos)
return "Health";
384 if (
lower.find(
"player") != std::string::npos &&
lower.find(
"binding") != std::string::npos)
return "PlayerBinding";
385 if (
lower.find(
"controller") != std::string::npos)
return "Controller";
386 if (
lower.find(
"audio") != std::string::npos ||
lower.find(
"sound") != std::string::npos)
return "Audio";
395 "sprite",
"spritePath",
"texture",
"texturePath",
"image",
"imagePath"
399 "audio",
"audioPath",
"sound",
"soundPath",
"music",
"musicPath"
403 "model",
"modelPath",
"mesh",
"meshPath"
414 std::string
key =
it.key();
421 std::string path =
it.value().get<std::string>();
434 std::string path =
it.value().get<std::string>();
447 std::string path =
it.value().get<std::string>();
456 if (
it.value().is_object() ||
it.value().is_array())
462 else if (
obj.is_array())
476 size_t pos = filepath.find_last_of(
"/\\");
477 if (
pos != std::string::npos)
479 return filepath.substr(
pos + 1);
487 if (
pos != std::string::npos)
500 const size_t m =
s1.size();
501 const size_t n =
s2.size();
503 if (
m == 0)
return static_cast<int>(
n);
504 if (
n == 0)
return static_cast<int>(
m);
506 std::vector<std::vector<int>>
costs(
m + 1, std::vector<int>(
n + 1));
511 for (
size_t i = 1;
i <=
m; ++
i)
513 for (
size_t j = 1;
j <=
n; ++
j)
529 if (
str1.empty() ||
str2.empty())
return 0.0f;
535 if (
maxLen == 0)
return 1.0f;
537 return 1.0f - (
static_cast<float>(
distance) /
static_cast<float>(
maxLen));
542 std::string filepath =
directory +
"/EntityPrefabSynonymsRegister.json";
544 SYSTEM_LOG <<
"Step 1/3: Loading synonym registry...\n";
545 SYSTEM_LOG <<
" Loading: " << filepath <<
"\n";
548 std::ifstream
file(filepath);
551 SYSTEM_LOG <<
" /!\\ Synonym registry not found, using default behavior\n";
562 if (
j.contains(
"fallbackBehavior") &&
j[
"fallbackBehavior"].is_object())
564 const json&
fb =
j[
"fallbackBehavior"];
573 if (
j.contains(
"categories") &&
j[
"categories"].is_object())
575 for (
const auto&
pair :
j[
"categories"].items())
577 const std::string& category =
pair.first;
580 if (types.is_array())
583 for (
const auto& type : types)
585 if (type.is_string())
587 typeList.push_back(type.get<std::string>());
598 if (
j.contains(
"canonicalTypes") &&
j[
"canonicalTypes"].is_object())
600 for (
const auto&
pair :
j[
"canonicalTypes"].items())
608 if (
info.contains(
"description") &&
info[
"description"].is_string())
610 synInfo.description =
info[
"description"].get<std::string>();
613 if (
info.contains(
"prefabFile") &&
info[
"prefabFile"].is_string())
615 synInfo.prefabFile =
info[
"prefabFile"].get<std::string>();
628 if (
info.contains(
"synonyms") &&
info[
"synonyms"].is_array())
664 catch (
const std::exception&
e)
666 SYSTEM_LOG <<
" /!\\ Failed to parse synonym registry: " <<
e.what() <<
"\n";
677 if (dataJson.contains(
"components") && dataJson[
"components"].is_array())
679 for (
const auto&
comp : dataJson[
"components"])
681 if (
comp.contains(
"type") &&
comp[
"type"].is_string())
686 if (
comp.contains(
"properties") &&
comp[
"properties"].is_object())
689 if (
props.contains(
"entityType") &&
props[
"entityType"].is_string())
691 return props[
"entityType"].get<std::string>();
703 std::string type =
prefabJson[
"type"].get<std::string>();
704 if (type !=
"EntityPrefab")
715 if (type.empty())
return type;
775 SYSTEM_LOG <<
" /!\\ Unmatched type: '" << type <<
"'\n";
821 SYSTEM_LOG <<
"+===========================================================+\n";
822 SYSTEM_LOG <<
"| PREFAB SCANNER: INITIALIZATION |\n";
823 SYSTEM_LOG <<
"+===========================================================+\n";
829 SYSTEM_LOG <<
"Step 1/4: Loading parameter schemas...\n";
834 SYSTEM_LOG <<
" -> Using built-in schemas as fallback\n";
844 SYSTEM_LOG <<
"\nStep 2/4: Loading synonym registry...\n";
849 SYSTEM_LOG <<
"\nStep 3/4: Scanning prefab directory...\n";
860 [](
const std::string&
file) {
861 return file.find(
"EntityPrefabSynonymsRegister.json") != std::string::npos ||
862 file.find(
"ParameterSchemas.json") != std::string::npos;
870 SYSTEM_LOG <<
"\nStep 4/4: Parsing prefabs...\n";
898 const std::vector<std::string>& types =
categoryPair.second;
901 if (std::find(types.begin(), types.end(),
blueprint.prefabType) != types.end())
914 for (
size_t i = 0;
i <
blueprint.categories.size();
i++)
928 SYSTEM_LOG <<
" X " << filepath <<
" (parse failed)\n";
933 SYSTEM_LOG <<
"+===========================================================+\n";
934 SYSTEM_LOG <<
"| PREFAB SCANNER: INITIALIZATION COMPLETE |\n";
935 SYSTEM_LOG <<
"+===========================================================+\n";
936 SYSTEM_LOG <<
"| Total Files Scanned: " << std::left << std::setw(33) <<
prefabFiles.size() <<
"|\n";
941 SYSTEM_LOG <<
"+===========================================================+\n\n";
ComponentTypeID GetComponentTypeID_Static()
int LevenshteinDistance(const std::string &s1, const std::string &s2)
static ParameterSchemaRegistry & GetInstance()
void DiscoverSchemasFromPrefab(const PrefabBlueprint &prefab)
size_t GetSchemaCount() const
const PrefabBlueprint * Find(const std::string &name) const
std::map< std::string, std::string > m_typeToName
std::vector< const PrefabBlueprint * > FindByType(const std::string &type) const
std::vector< std::string > GetAllPrefabNames() const
void Register(const PrefabBlueprint &blueprint)
std::map< std::string, PrefabBlueprint > m_blueprints
std::string NormalizeType(const std::string &type) const
Normalize a type string to canonical form.
PrefabBlueprint ParsePrefab(const std::string &filepath)
std::vector< PrefabBlueprint > ScanDirectory(const std::string &rootPath)
std::map< std::string, std::string > m_synonymToCanonical
std::string DetectComponentType(const std::string &typeName)
std::string ToUpper(const std::string &str) const
std::string ExtractPrefabType(const nlohmann::json &prefabJson)
bool LoadSynonymRegistry(const std::string &directory)
bool GetCanonicalInfo(const std::string &type, std::string &outCanonical, std::string &outPrefabFile) const
Get canonical type info (for debugging)
std::map< std::string, std::vector< std::string > > m_categoryToTypes
PrefabRegistry Initialize(const std::string &prefabDirectory="Gamedata/EntityPrefab")
Initialize the prefab system (call once at startup)
bool IsTypeRegistered(const std::string &type) const
Check if a type is registered.
void ExtractResources(const nlohmann::json &componentsJson, ResourceRefs &outResources)
bool AreTypesEquivalent(const std::string &type1, const std::string &type2) const
Check if two types are equivalent.
bool m_enableFuzzyMatching
std::string RemoveExtension(const std::string &filename)
std::string GetFilename(const std::string &filepath)
float FuzzyMatch(const std::string &str1, const std::string &str2) const
void ScanDirectoryRecursive_Unix(const std::string &path, std::vector< std::string > &outFiles)
std::map< std::string, SynonymInfo > m_canonicalTypes
static ComponentDefinition FromJSON(const nlohmann::json &jsonObj)
std::string canonicalType