37#include "../SDL/include/SDL3_image/SDL_image.h"
125 SYSTEM_LOG <<
"+===========================================================+\n";
126 SYSTEM_LOG <<
"| ANIMATION SYSTEM: LOADING RESOURCES |\n";
127 SYSTEM_LOG <<
"+===========================================================+\n";
215 system->AddEntity(entity);
220 system->RemoveEntity(entity);
228 using namespace std::chrono;
232 auto now = system_clock::now();
273 pair.second->RemoveComponent(entity);
287 std::cout <<
"Entit� " << entity <<
" d�truite et ID recycl�.\n";
296 SYSTEM_LOG <<
"/!\\ World::SetEntityLayer: Entity " << entity
297 <<
" has no Position_data component\n";
304 SYSTEM_LOG <<
"World::SetEntityLayer: Entity " << entity
305 <<
" assigned to layer " <<
static_cast<int>(layer)
306 <<
" (z=" <<
pos.position.z <<
")\n";
350 #ifdef OLYMPE_BLUEPRINT_EDITOR_ENABLED
357 #ifdef OLYMPE_BLUEPRINT_EDITOR_ENABLED
377 std::string orientation =
levelDef.mapConfig.orientation;
378 if (orientation.empty())
380 orientation =
"orthogonal";
381 SYSTEM_LOG <<
"World::SyncGridWithLevel: Warning - No orientation specified, using orthogonal\n";
385 int tileWidth =
levelDef.mapConfig.tileWidth > 0 ?
levelDef.mapConfig.tileWidth : 32;
386 int tileHeight =
levelDef.mapConfig.tileHeight > 0 ?
levelDef.mapConfig.tileHeight : 32;
389 if (orientation ==
"orthogonal")
393 static_cast<float>(tileHeight), 0.f);
395 else if (orientation ==
"isometric")
399 static_cast<float>(tileHeight), 0.f);
401 else if (orientation ==
"hexagonal")
406 settings.hexRadius =
static_cast<float>(tileWidth) / 2.0f;
408 else if (orientation ==
"staggered")
412 SYSTEM_LOG <<
"World::SyncGridWithLevel: Warning - Staggered orientation not fully supported, using orthogonal\n";
415 static_cast<float>(tileHeight), 0.f);
420 SYSTEM_LOG <<
"World::SyncGridWithLevel: Warning - Unknown orientation '"
421 << orientation <<
"', using orthogonal\n";
424 static_cast<float>(tileHeight), 0.f);
427 SYSTEM_LOG <<
"World::SyncGridWithLevel: Grid synced with level\n"
428 <<
" Orientation: " << orientation <<
"\n"
429 <<
" Tile size: " << tileWidth <<
"x" << tileHeight <<
"\n";
437 SYSTEM_LOG <<
"World::SyncGridWithLevel: Warning - No GridSettings entity found, grid sync skipped\n";
448 if (!layer)
return false;
454 [](
unsigned char c) { return std::tolower(c); });
463 for (std::map<std::string, Olympe::Tiled::TiledProperty>::const_iterator
propIt = layer->properties.begin();
466 if (
propIt->second.name ==
"collision" &&
propIt->second.boolValue ==
true)
487 SYSTEM_LOG <<
"+==========================================================+\n";
488 SYSTEM_LOG <<
"| COLLISION & NAVIGATION MAP GENERATION |\n";
489 SYSTEM_LOG <<
"+==========================================================+\n";
492 SYSTEM_LOG <<
" [DEBUG] TMJ Structure Analysis:\n";
498 <<
", mapHeight=" <<
levelDef.mapConfig.mapHeight <<
"\n";
500 <<
", tileHeight=" <<
levelDef.mapConfig.tileHeight <<
"\n";
506 SYSTEM_LOG <<
" [DEBUG] Scanning tile layers for dimensions:\n";
510 const std::shared_ptr<Olympe::Tiled::TiledLayer>& layer =
tiledMap.layers[
layerIdx];
513 SYSTEM_LOG <<
" Layer '" << layer->name <<
"': "
514 << layer->width <<
"x" << layer->height
515 <<
" (data size: " << layer->data.size() <<
")\n";
517 mapWidth = std::max(mapWidth, layer->width);
518 mapHeight = std::max(mapHeight, layer->height);
523 if (mapWidth == 0 || mapHeight == 0)
526 mapWidth =
levelDef.mapConfig.tileWidth;
527 mapHeight =
levelDef.mapConfig.tileHeight;
529 SYSTEM_LOG <<
" WARNING: No tile layers found, using tileWidth/tileHeight as fallback\n";
532 SYSTEM_LOG <<
" TMJ declared dimensions (metadata): "
533 <<
levelDef.mapConfig.mapWidth <<
"x" <<
levelDef.mapConfig.mapHeight <<
"\n";
534 SYSTEM_LOG <<
" Actual tile grid dimensions (calculated): "
535 << mapWidth <<
"x" << mapHeight <<
"\n";
537 if (mapWidth == 0 || mapHeight == 0)
539 SYSTEM_LOG <<
" X Invalid map dimensions, skipping collision/navigation generation\n\n";
544 std::string orientation =
levelDef.mapConfig.orientation;
546 if (orientation ==
"isometric")
548 else if (orientation ==
"hexagonal")
561 SYSTEM_LOG <<
" X Invalid or unreasonable tile pixel dimensions from TMJ ("
568 SYSTEM_LOG <<
" Projection: " << orientation <<
" (type=" <<
static_cast<int>(projection) <<
")\n";
603 SYSTEM_LOG <<
" -> Applying standard isometric offset heuristic: (0, "
618 SYSTEM_LOG <<
" -> CollisionMap initialized: " << mapWidth <<
"x" << mapHeight
619 <<
" (" << (mapWidth * mapHeight) <<
" tiles)\n";
620 SYSTEM_LOG <<
" -> NavigationMap initialized: " << mapWidth <<
"x" << mapHeight <<
"\n";
626 SYSTEM_LOG <<
" [1/2] Processing tile layers for navigation...\n";
635 const int dx[] = {-1, 0, 1, -1, 1, -1, 0, 1};
636 const int dy[] = {-1, -1, -1, 0, 0, 1, 1, 1};
640 const std::shared_ptr<Olympe::Tiled::TiledLayer>& layer =
tiledMap.layers[
layerIdx];
641 if (!layer)
continue;
650 if (!
props.hasNavigationProperties)
652 SYSTEM_LOG <<
" Skipping graphic-only layer: " << layer->name <<
"\n";
657 SYSTEM_LOG <<
" Layer '" << layer->name <<
"' navigation properties:\n";
658 SYSTEM_LOG <<
" - isTilesetWalkable: " << (
props.isTilesetWalkable ?
"true" :
"false") <<
"\n";
659 SYSTEM_LOG <<
" - useTilesetBorder: " << (
props.useTilesetBorder ?
"true" :
"false") <<
"\n";
662 int layerW = std::min(layer->width, mapWidth);
663 int layerH = std::min(layer->height, mapHeight);
672 for (
int y = 0; y <
layerH; ++y)
674 for (
int x = 0; x <
layerW; ++x)
676 if (
index >=
static_cast<int>(layer->data.size()))
691 if (
props.isTilesetWalkable)
719 if (
props.useTilesetBorder)
722 for (
int y = 0; y <
layerH; ++y)
724 for (
int x = 0; x <
layerW; ++x)
726 if (
index >=
static_cast<int>(layer->data.size()))
break;
780 if (
props.useTilesetBorder)
803 SYSTEM_LOG <<
" [2/2] Processing explicit collision object layers (if any)...\n";
810 const std::shared_ptr<Olympe::Tiled::TiledLayer>& layer =
tiledMap.layers[
layerIdx];
811 if (!layer)
continue;
817 if (!IsCollisionLayer(layer))
continue;
819 SYSTEM_LOG <<
" Processing collision objects from layer: " << layer->name <<
"\n";
869 SYSTEM_LOG <<
" -> Collision & Navigation maps ready\n";
870 SYSTEM_LOG <<
" Grid dimensions: " << mapWidth <<
"x" << mapHeight
871 <<
" (" << (mapWidth * mapHeight) <<
" total tiles)\n";
880 SYSTEM_LOG <<
" DEBUG: Verifying tile data can be read back...\n";
889 if (
tile.isNavigable && !
tile.isBlocked)
894 SYSTEM_LOG <<
" -> Sample navigable tile at (" << x <<
"," << y <<
")\n";
897 else if (
tile.isBlocked)
902 SYSTEM_LOG <<
" -> Sample blocked tile at (" << x <<
"," << y <<
")\n";
911 SYSTEM_LOG <<
"+==========================================================+\n";
928 std::cout <<
"\n+===========================================================+\n";
929 std::cout <<
"| LEVEL DEPENDENCY LOADING |\n";
930 std::cout <<
"+===========================================================+\n";
933 std::cout <<
"Step 1/3: Extracting prefab types from level...\n";
938 std::cout <<
" -> No prefabs found in level (this may be normal for tile-only levels)\n";
939 std::cout <<
"+===========================================================+\n\n";
943 std::cout <<
" -> Found " <<
prefabNames.size() <<
" unique prefab type(s):\n";
946 std::cout <<
" - " << name <<
"\n";
950 std::cout <<
"\nStep 2/3: Scanning prefabs for behavior tree dependencies...\n";
956 std::cout <<
" -> No behavior trees required for this level\n";
957 std::cout <<
"+===========================================================+\n\n";
962 std::cout <<
"\nStep 3/3: Loading required behavior trees...\n";
972 std::cout <<
" [CACHED] " <<
dep.treePath <<
" (ID=" <<
dep.suggestedTreeId <<
")\n";
978 std::cout <<
" [LOADING] " <<
dep.treePath <<
" (ID=" <<
dep.suggestedTreeId <<
")... ";
982 std::cout <<
"SUCCESS\n";
987 std::cout <<
"FAILED\n";
988 std::cerr <<
" [ERROR] Failed to load behavior tree: " <<
dep.treePath <<
"\n";
994 std::cout <<
"\n+===========================================================+\n";
995 std::cout <<
"| DEPENDENCY LOADING SUMMARY |\n";
996 std::cout <<
"+===========================================================+\n";
997 std::cout <<
"| Behavior Trees Required: " <<
btDeps.size() <<
"\n";
998 std::cout <<
"| Loaded This Session: " <<
loaded <<
"\n";
1000 std::cout <<
"| Failed: " << failed <<
"\n";
1001 std::cout <<
"+===========================================================+\n\n";
1003 return (failed == 0);
1012 std::cout <<
"+==========================================================+\n";
1013 std::cout <<
"| LEVEL LOADING PIPELINE (6 PHASES) |\n";
1014 std::cout <<
"+==========================================================+\n\n";
1021 SYSTEM_LOG <<
"Phase 1: -> Prefab System Ready (" <<
factory.GetPrefabCount() <<
" prefabs)\n\n";
1027 SYSTEM_LOG <<
"+==========================================================+\n";
1028 SYSTEM_LOG <<
"| PHASE 2: LEVEL PARSING |\n";
1029 SYSTEM_LOG <<
"+==========================================================+\n";
1038 SYSTEM_LOG <<
" X Failed to load TMJ file\n";
1052 SYSTEM_LOG <<
" -> Static objects: " <<
levelDef.categorizedObjects.staticObjects.size() <<
"\n";
1053 SYSTEM_LOG <<
" -> Dynamic objects: " <<
levelDef.categorizedObjects.dynamicObjects.size() <<
"\n";
1054 SYSTEM_LOG <<
" -> Patrol paths: " <<
levelDef.categorizedObjects.patrolPaths.size() <<
"\n\n";
1057 SYSTEM_LOG <<
"[Phase 5/6] Generating Collision & Navigation Maps...\n";
1085 std::cerr <<
"[World] ERROR: Failed to load level dependencies\n";
1089 catch (
const std::exception&
e)
1091 std::cerr <<
"[World] WARNING: Failed to parse level JSON: " <<
e.what() <<
"\n";
1097 std::cerr <<
"[World] WARNING: Could not open level JSON file for dependency scanning\n";
1105 SYSTEM_LOG <<
"+==========================================================+\n";
1106 SYSTEM_LOG <<
"| PHASE 3: RESOURCE PRELOADING |\n";
1107 SYSTEM_LOG <<
"+==========================================================+\n\n";
1115 SYSTEM_LOG <<
" Step 1/4: Loading tilesets...\n";
1116 if (!
levelDef.resources.tilesetPaths.empty())
1128 SYSTEM_LOG <<
" Step 2/4: Loading parallax layers...\n";
1130 if (
levelDef.metadata.customData.contains(
"parallaxLayers") &&
levelDef.metadata.customData[
"parallaxLayers"].is_array())
1135 std::string imagePath =
layerJson.value(
"imagePath",
"");
1136 if (!imagePath.empty())
1151 SYSTEM_LOG <<
" Step 3/4: Loading prefab sprites...\n";
1153 std::set<std::string> uniqueTypes;
1154 for (
const auto& entity :
levelDef.entities)
1158 uniqueTypes.insert(entity->type);
1162 for (
const auto& type : uniqueTypes)
1167 for (
const auto& sprite :
blueprint->resources.spriteRefs)
1183 SYSTEM_LOG <<
" Step 4/4: Loading audio files...\n";
1184 if (!
levelDef.resources.audioPaths.empty())
1203 SYSTEM_LOG <<
"+==========================================================+\n";
1204 SYSTEM_LOG <<
"| PHASE 4: VISUAL STRUCTURE CREATION |\n";
1205 SYSTEM_LOG <<
"+==========================================================+\n\n";
1210 SYSTEM_LOG <<
" Pass 1/2: Parallax & Visual Layers...\n";
1213 SYSTEM_LOG <<
" Pass 2/2: Spatial Structures...\n";
1222 SYSTEM_LOG <<
"+==========================================================+\n";
1223 SYSTEM_LOG <<
"| PHASE 5: ENTITY INSTANTIATION |\n";
1224 SYSTEM_LOG <<
"+==========================================================+\n\n";
1227 SYSTEM_LOG <<
" Pass 1/3: Static objects...\n";
1237 SYSTEM_LOG <<
" -> Created " <<
instResult.pass3_staticObjects.successfullyCreated <<
" objects\n\n";
1240 SYSTEM_LOG <<
" Pass 2/3: Dynamic objects...\n";
1252 SYSTEM_LOG <<
" -> Created " <<
instResult.pass4_dynamicObjects.successfullyCreated <<
" objects\n\n";
1255 SYSTEM_LOG <<
" Pass 3/3: Spatial structures (patrol paths)...\n";
1265 SYSTEM_LOG <<
" -> Created " <<
instResult.pass5_relationships.successfullyCreated <<
" objects\n\n";
1271 SYSTEM_LOG <<
"+==========================================================+\n";
1272 SYSTEM_LOG <<
"| PHASE 6: ENTITY RELATIONSHIPS |\n";
1273 SYSTEM_LOG <<
"+==========================================================+\n\n";
1277 SYSTEM_LOG <<
" -> Linked " <<
instResult.pass5_relationships.linkedObjects <<
" relationships\n\n";
1285 SYSTEM_LOG <<
"+==========================================================+\n";
1286 SYSTEM_LOG <<
"| LEVEL LOADING COMPLETE |\n";
1287 SYSTEM_LOG <<
"+==========================================================+\n";
1289 << std::string(31,
' ') <<
"|\n";
1291 << std::string(31,
' ') <<
"|\n";
1293 << std::string(31,
' ') <<
"|\n";
1295 << std::string(31,
' ') <<
"|\n";
1296 SYSTEM_LOG <<
"+==========================================================+\n\n";
1298 SYSTEM_LOG <<
"World::LoadLevelFromTiled - Level loaded successfully\n";
1304 SYSTEM_LOG <<
"World::UnloadCurrentLevel - Unloading current level\n";
1336 if (
id.isPersistent)
1338 SYSTEM_LOG <<
"World::UnloadCurrentLevel - Keeping persistent entity: " <<
e <<
" (" <<
id.name <<
")\n";
1366 for (
const auto& entity :
levelDef.entities)
1368 if (!entity)
continue;
1388 const std::shared_ptr<Olympe::Editor::EntityInstance>&
entityInstance,
1411 if (
blueprint->HasCategory(
"RequiresRegistration"))
1418 <<
"': no input device available (all joysticks and keyboard already assigned)\n";
1449 if (
blueprint->HasCategory(
"RequiresRegistration"))
1468 <<
" (layer: " <<
static_cast<int>(layer) <<
", z: " <<
pos.position.z <<
")"
1495 int minTileX =
levelDef.metadata.customData.value(
"minTileX", 0);
1496 int minTileY =
levelDef.metadata.customData.value(
"minTileY", 0);
1497 int maxTileX =
levelDef.metadata.customData.value(
"maxTileX", 0);
1498 int maxTileY =
levelDef.metadata.customData.value(
"maxTileY", 0);
1510 SYSTEM_LOG <<
"[World] Isometric origin calculated: ("
1515 if (
levelDef.metadata.customData.contains(
"parallaxLayers"))
1527 std::string imagePath =
layerJson.value(
"imagePath",
"");
1528 if (imagePath.empty())
1530 result.pass1_visualLayers.failed++;
1531 result.pass1_visualLayers.failedObjects.push_back(
"<missing imagePath>");
1532 std::cout <<
" x Failed: parallax layer missing imagePath\n";
1539 size_t lastSlash = imagePath.find_last_of(
"/\\");
1549 result.pass1_visualLayers.failed++;
1550 result.pass1_visualLayers.failedObjects.push_back(imagePath);
1551 std::cout <<
" x Failed to load parallax layer: " << imagePath <<
"\n";
1571 result.pass1_visualLayers.successfullyCreated++;
1572 std::cout <<
" -> Loaded parallax layer: " << layer.
name <<
"\n";
1578 if (
levelDef.metadata.customData.contains(
"tilesets"))
1580 std::cout <<
"-> Loading tilesets...\n";
1585 if (
levelDef.metadata.customData.contains(
"tileLayers"))
1591 std::cout <<
"-> Loading " <<
tileLayersJson.size() <<
" tile layers...\n";
1634 std::string layerName =
layerJson.value(
"name",
"unnamed_layer");
1635 int zOrder =
layerJson.value(
"zOrder", 0);
1636 bool visible =
layerJson.value(
"visible",
true);
1637 float opacity =
layerJson.value(
"opacity", 1.0f);
1638 std::string encoding =
layerJson.value(
"encoding",
"");
1642 std::cout <<
" ⊙ Skipping invisible layer: " << layerName <<
"\n";
1646 result.pass1_visualLayers.totalObjects++;
1651 const auto& chunks =
layerJson[
"chunks"];
1653 std::cout <<
" -> Tile Layer (Infinite): " << layerName
1654 <<
" (" << chunks.size() <<
" chunks, encoding: " << encoding <<
", z: " << zOrder <<
")\n";
1656 for (
size_t i = 0;
i < chunks.size(); ++
i)
1661 result.pass1_visualLayers.successfullyCreated++;
1666 int width =
layerJson.value(
"width", 0);
1667 int height =
layerJson.value(
"height", 0);
1669 std::cout <<
" -> Tile Layer (Finite): " << layerName
1670 <<
" (" << width <<
"x" << height <<
", z: " << zOrder <<
")\n";
1673 result.pass1_visualLayers.successfullyCreated++;
1677 std::cout <<
" x Tile layer missing data: " << layerName <<
"\n";
1678 result.pass1_visualLayers.failed++;
1683 int zOrder,
const std::string& encoding)
1691 std::vector<uint32_t> tileGIDs;
1708 for (
const auto& gid :
chunkJson[
"data"])
1710 tileGIDs.push_back(gid.get<
uint32_t>());
1715 if (tileGIDs.empty())
1717 std::cout <<
" x Failed to decode chunk at (" <<
chunkX <<
", " <<
chunkY <<
")\n";
1728 chunk.zOrder = zOrder;
1729 chunk.tileGIDs = tileGIDs;
1733 std::cout <<
" ok - Loaded chunk at (" <<
chunkX <<
", " <<
chunkY
1734 <<
") - " << tileGIDs.size() <<
" tiles\n";
1738 int width,
int height,
int zOrder,
const std::string& encoding)
1740 std::vector<uint32_t> tileGIDs;
1742 if (dataJson.is_string())
1745 std::string
dataStr = dataJson.get<std::string>();
1748 else if (dataJson.is_array())
1751 for (
const auto&
tile : dataJson)
1757 if (tileGIDs.empty())
1759 std::cout <<
" x No tile data for layer: " << layerName <<
"\n";
1768 chunk.width = width;
1769 chunk.height = height;
1770 chunk.zOrder = zOrder;
1771 chunk.tileGIDs = tileGIDs;
1786 if (tileset.texture)
1789 tileset.texture =
nullptr;
1792 for (
auto&
pair : tileset.individualTiles)
1799 tileset.individualTiles.clear();
1821 std::string sourceFile =
tilesetJson[
"source"].get<std::string>();
1823 SYSTEM_LOG <<
" -> Loading external tileset: " << sourceFile <<
"\n";
1826 std::string
baseDir =
"Gamedata/Levels/";
1827 std::string fullPath =
baseDir + sourceFile;
1854 SYSTEM_LOG <<
"[TilesetManager] ========================================+\n";
1855 SYSTEM_LOG <<
"[TilesetManager] Loading external tileset: " <<
info.name <<
"\n";
1856 SYSTEM_LOG <<
"[TilesetManager] Parsed global offset from cache: ("
1857 <<
info.tileoffsetX <<
", " <<
info.tileoffsetY <<
")\n";
1858 SYSTEM_LOG <<
"[TilesetManager] GID range: " <<
info.firstgid <<
" - "
1866 info.lastgid =
info.firstgid + tilecount - 1;
1877 size_t lastSlash = imagePath.find_last_of(
"/\\");
1879 imagePath.substr(
lastSlash + 1) : imagePath;
1890 SYSTEM_LOG <<
"[TilesetManager] Image-based tileset - All "
1891 << tilecount <<
" tiles will use offset ("
1892 <<
info.tileoffsetX <<
", " <<
info.tileoffsetY <<
")\n";
1893 SYSTEM_LOG <<
"[TilesetManager] ========================================+\n";
1901 else if (
info.isCollection)
1911 if (
tile.image.empty())
continue;
1915 std::string imagePath =
tile.image;
1918 size_t lastSlash = imagePath.find_last_of(
"/\\");
1920 imagePath.substr(
lastSlash + 1) : imagePath;
1935 srcRect.w =
tile.imagewidth > 0 ?
tile.imagewidth :
info.tilewidth;
1936 srcRect.h =
tile.imageheight > 0 ?
tile.imageheight :
info.tileheight;
1942 if (
loadedCount <= 3 || (gid >= 127 && gid <= 135))
1945 <<
" (" << srcRect.w <<
"x" << srcRect.h <<
")"
1946 <<
" - STORED with tileset offset: ("
1947 <<
info.tileoffsetX <<
", " <<
info.tileoffsetY <<
")\n";
1953 SYSTEM_LOG <<
"[TilesetManager] ok - Loaded collection tileset: " <<
info.name
1954 <<
" (" <<
info.individualTiles.size() <<
" tiles)\n";
1955 SYSTEM_LOG <<
"[TilesetManager] All tiles stored with global offset: ("
1956 <<
info.tileoffsetX <<
", " <<
info.tileoffsetY <<
")\n";
1957 SYSTEM_LOG <<
"[TilesetManager] ========================================+\n";
1962 SYSTEM_LOG <<
" x Failed to load external tileset: " << sourceFile <<
"\n";
1989 SYSTEM_LOG <<
" [TilesetManager] Embedded tileset '" <<
info.name <<
"'"
1990 <<
" - Global tileoffset: (" <<
info.tileoffsetX
1991 <<
", " <<
info.tileoffsetY <<
")\n";
1996 info.tileoffsetX = 0;
1997 info.tileoffsetY = 0;
2001 info.lastgid =
info.firstgid + tilecount - 1;
2003 info.isCollection = (
info.columns == 0);
2008 std::string imagePath =
tilesetJson[
"image"].get<std::string>();
2010 size_t lastSlash = imagePath.find_last_of(
"/\\");
2012 imagePath.substr(
lastSlash + 1) : imagePath;
2016 if (!fullPath.empty())
2022 <<
" (gid: " <<
info.firstgid <<
"-" <<
info.lastgid <<
")\n";
2026 SYSTEM_LOG <<
" x Failed to load embedded tileset texture: " << fullPath <<
"\n";
2037 std::string imagePath =
tileJson[
"image"].get<std::string>();
2039 size_t lastSlash = imagePath.find_last_of(
"/\\");
2041 imagePath.substr(
lastSlash + 1) : imagePath;
2045 if (!fullPath.empty())
2062 SYSTEM_LOG <<
" ok - Loaded embedded collection tileset: " <<
info.name
2063 <<
" (" <<
info.individualTiles.size() <<
" tiles)\n";
2075 SYSTEM_LOG <<
"[TilesetManager] X ERROR: Offset LOST during vector storage!\n";
2079 else if (
info.tileoffsetX != 0 ||
info.tileoffsetY != 0)
2081 SYSTEM_LOG <<
"[TilesetManager] ok - POST-INSERT verification: offset=("
2101 return a.firstgid > b.firstgid;
2104 SYSTEM_LOG <<
"\n[TilesetManager] ========================================+\n";
2105 SYSTEM_LOG <<
"[TilesetManager] Tileset load complete. Final ordering (by firstgid DESC):\n";
2109 <<
" [" << tileset.firstgid <<
" - " << tileset.lastgid <<
"]"
2110 <<
" offset=(" << tileset.tileoffsetX <<
", " << tileset.tileoffsetY <<
")\n";
2128 if (
ts1.firstgid <=
ts2.lastgid)
2131 SYSTEM_LOG <<
" [WARNING] GID range overlap detected!\n";
2133 <<
"' [" <<
ts1.firstgid <<
"-" <<
ts1.lastgid <<
"]\n";
2135 <<
"' [" <<
ts2.firstgid <<
"-" <<
ts2.lastgid <<
"]\n";
2136 SYSTEM_LOG <<
" -> GetTileTexture() will prioritize '" <<
ts1.name
2137 <<
"' due to higher firstgid\n";
2144 SYSTEM_LOG <<
" [OK] No GID range overlaps detected\n";
2146 SYSTEM_LOG <<
"[TilesetManager] ========================================+\n";
2203 "[TILESET] NULL texture for collection tile GID=%u, localId=%u", gid, localId);
2213 "[TILESET] Collection tile not found: GID=%u, localId=%u", gid, localId);
2222 "[TILESET] NULL texture for tileset '%s' (GID=%u)", tileset.
name.c_str(), gid);
2243 <<
" NOT FOUND in any tileset (total tilesets: " <<
m_tilesets.size() <<
")\n";
2274 SYSTEM_LOG <<
"\n[Pass 5] Linking object relationships...\n";
2280 if (
link.linkType ==
"patrol_path") {
2284 SYSTEM_LOG <<
" x Guard '" <<
link.sourceObjectName <<
"' not found in registry\n";
2285 result.pass5_relationships.failed++;
2292 SYSTEM_LOG <<
" x Patrol path '" <<
link.targetObjectName <<
"' not found in registry\n";
2293 result.pass5_relationships.failed++;
2319 <<
"' -> patrol '" <<
link.targetObjectName
2322 result.pass5_relationships.linkedObjects++;
2326 <<
"' missing AIBlackboard_data\n";
2327 result.pass5_relationships.failed++;
2331 <<
"' missing AIBlackboard_data\n";
2332 result.pass5_relationships.failed++;
2345 if (
it ==
result.entityRegistry.end())
continue;
2354 result.pass5_relationships.totalObjects++;
2368 static_cast<float>(
patrolPath[
i][
"x"].get<
float>());
2370 static_cast<float>(
patrolPath[
i][
"y"].get<
float>());
2376 result.pass5_relationships.successfullyCreated++;
2377 std::cout <<
" -> Assigned " <<
blackboard.patrolPointCount
2398 if (value.is_number_float())
2402 else if (value.is_number_integer())
2406 else if (value.is_boolean())
2410 else if (value.is_string())
2414 else if (value.is_array())
2417 if (value.size() >= 2 && value.size() <= 3 && value[0].is_number())
2427 x = value[0].get<
float>();
2433 y = value[1].get<
float>();
2438 if (value.size() >= 3) {
2440 z = value[2].get<
float>();
2447 SYSTEM_LOG <<
"[World] WARNING: Vector array contains non-numeric elements: "
2448 << value.dump() <<
". Non-numeric values defaulted to 0.0f." << std::endl;
2483 for (
const auto&
comp :
prefab->components) {
2484 if (
comp.componentType == componentType)
2505 if (!overrides.is_null())
2507 if (overrides.contains(
"point") && overrides[
"point"].is_boolean())
2510 if (!
isPointObject && overrides.contains(
"width") && overrides.contains(
"height"))
2512 if (overrides[
"width"].
is_number() && overrides[
"height"].is_number())
2514 float w = overrides[
"width"].get<
float>();
2515 float h = overrides[
"height"].get<
float>();
2516 if (
w == 0.0f &&
h == 0.0f)
2536 if (!overrides.is_null())
2539 if (overrides.contains(
"width") && overrides[
"width"].is_number())
2541 if (overrides.contains(
"height") && overrides[
"height"].is_number())
2543 if (overrides.contains(
"x") && overrides[
"x"].is_number())
2545 if (overrides.contains(
"y") && overrides[
"y"].is_number())
2560 instanceParams.componentOverrides[
"BoundingBox_data"][
"height"] =
2585 if (!overrides.is_null())
2587 if (overrides.contains(
"width") && overrides[
"width"].is_number())
2588 tmjWidth = overrides[
"width"].get<
float>();
2589 if (overrides.contains(
"height") && overrides[
"height"].is_number())
2591 if (overrides.contains(
"x") && overrides[
"x"].is_number())
2593 if (overrides.contains(
"y") && overrides[
"y"].is_number())
2613 instanceParams.componentOverrides[
"CollisionZone_data"][
"width"] =
2619 instanceParams.componentOverrides[
"CollisionZone_data"][
"height"] =
2628 <<
" TMJ overrides for '" <<
entityInstance->name <<
"'" << std::endl;
2637 if (!overrides.is_null())
2639 if (overrides.contains(
"rotation") && overrides[
"rotation"].is_number())
2646 instanceParams.componentOverrides[
"PhysicsBody_data"][
"rotation"] =
2656 if (!overrides.is_null())
2658 if (overrides.contains(
"visible") && overrides[
"visible"].is_boolean())
2659 tmjVisible = overrides[
"visible"].get<
bool>();
2666 instanceParams.componentOverrides[
"VisualSprite_data"][
"visible"] =
2676 if (overrides.is_null())
2679 for (
auto it = overrides.begin();
it != overrides.end(); ++
it)
2681 const std::string&
key =
it.key();
2682 const auto& value =
it.value();
2685 if (
key ==
"width" ||
key ==
"height" ||
key ==
"x" ||
key ==
"y" ||
key ==
"rotation" ||
key ==
"visible")
2694 if (value.is_object())
2753 SYSTEM_LOG <<
" /!\\ PLACEHOLDER: Created red marker for missing prefab '"
2762 std::string prefabName = prefabPath;
2765 size_t lastSlash = prefabName.find_last_of(
"/\\");
2767 prefabName = prefabName.substr(
lastSlash + 1);
2770 size_t lastDot = prefabName.find_last_of(
".");
2771 if (
lastDot != std::string::npos)
2772 prefabName = prefabName.substr(0,
lastDot);
2782 SYSTEM_LOG <<
"X World::RegisterPlayerEntity: Entity " << entity
2783 <<
" missing required player components (PlayerBinding_data, Controller_data)\n";
2807 SYSTEM_LOG <<
"[World] Map bounds set: tiles(" << minTileX <<
"," << minTileY
2808 <<
") to (" << maxTileX <<
"," << maxTileY <<
"), chunk origin: ("
Data-driven behavior tree system for AI decision making.
float LayerToZ(RenderLayer layer)
Convert layer enum to z-coordinate value.
RenderLayer ZToLayer(float z)
Convert z-coordinate to layer enum (rounds to nearest integer) Note: z-coordinates should exactly mat...
RenderLayer
Render layer enumeration for Z-ordering.
std::bitset< MAX_COMPONENTS > ComponentSignature
ComponentTypeID GetComponentTypeID_Static()
std::uint64_t ComponentTypeID
const EntityID INVALID_ENTITY_ID
Animation system for 2D sprite animation.
void NotifyEditorEntityCreated(uint64_t entity)
void NotifyEditorEntityDestroyed(uint64_t entity)
void RegisterInputEntityWithManager(EntityID e)
World and ECS Manager for Olympe Engine.
static std::vector< BTDependency > ScanPrefabs(const std::vector< std::string > &prefabNames)
static std::set< std::string > ExtractPrefabsFromLevel(const nlohmann::json &levelJson)
bool LoadTreeFromFile(const std::string &filepath, uint32_t treeId)
static BehaviorTreeManager & Get()
bool IsTreeLoadedByPath(const std::string &treePath) const
static CollisionMap & Get()
static DataManager & Get()
Sprite * GetSprite(const std::string &id, const std::string &path, ResourceCategory category=ResourceCategory::GameEntity)
std::string FindResourceRecursive(const std::string &filename, const std::string &rootDir="GameData") const
static SDL_Renderer * renderer
Main SDL renderer.
static NavigationMap & Get()
static AnimationManager & Get()
void LoadAnimationGraphs(const std::string &directoryPath)
void LoadAnimationBanks(const std::string &directoryPath)
static void CalculateTMJOrigin(int minTileX, int minTileY, int maxTileX, int maxTileY, int tileWidth, int tileHeight, float &outOriginX, float &outOriginY)
static ParallaxLayerManager & Get()
static std::vector< uint32_t > DecodeTileData(const std::string &data, const std::string &encoding, const std::string &compression)
std::shared_ptr< TiledTileset > GetTileset(const std::string &filepath)
static TilesetCache & GetInstance()
Factory class for creating entities from prefab blueprints.
static PrefabFactory & Get()
Get singleton instance.
void PreloadAllPrefabs(const std::string &prefabDirectory="Blueprints/EntityPrefab")
Preload all prefabs from directory.
void Clear()
Clear all loaded tilesets.
std::vector< TilesetInfo > m_tilesets
All loaded tilesets.
void LoadTilesets(const nlohmann::json &tilesetsJson)
Load tilesets from JSON data.
bool GetTileTexture(uint32_t gid, SDL_Texture *&outTexture, SDL_Rect &outSrcRect, const TilesetInfo *&outTileset)
Get texture and source rect for a tile by GID.
void RegisterLoadedPlayerEntity(EntityID entity)
static ViewportManager & Get()
void NotifyBlueprintEditorEntityCreated(EntityID entity)
std::queue< EntityID > m_freeEntityIDs
bool m_isometricOriginCached
bool InstantiatePass1_VisualLayers(const Olympe::Editor::LevelDefinition &levelDef, InstantiationResult &result)
EntityID CreateMissingPrefabPlaceholder(const Olympe::Editor::EntityInstance &entityInstance, InstantiationResult::PassStats &stats)
Create a red placeholder entity for missing prefabs.
EntityID InstantiateEntity(const std::shared_ptr< Olympe::Editor::EntityInstance > &entityInstance, PrefabFactory &factory, InstantiationResult::PassStats &stats)
Unified entity instantiation helper (used by all Phase 5 passes) Types are already normalized,...
void Initialize_ECS_Systems()
void UnloadCurrentLevel()
bool LoadLevelFromTiled(const std::string &tiledMapPath)
void NotifyBlueprintEditorEntityDestroyed(EntityID entity)
void Render_ECS_Systems()
void LoadTileLayer(const nlohmann::json &layerJson, InstantiationResult &result)
std::string ExtractPrefabName(const std::string &prefabPath)
Extract prefab name from prefab path (removes path and extension)
void LoadTileData(const nlohmann::json &dataJson, const std::string &layerName, int width, int height, int zOrder, const std::string &encoding)
static World & Get()
Get singleton instance (short form)
T & AddComponent(EntityID entity, Args &&... args)
void SyncGridWithLevel(const Olympe::Editor::LevelDefinition &levelDef)
Synchronize grid settings with loaded level Extracts map orientation and tile dimensions from LevelDe...
void LoadTileChunk(const nlohmann::json &chunkJson, const std::string &layerName, int zOrder, const std::string &encoding)
bool LoadLevelDependencies(const nlohmann::json &levelJson)
std::unordered_map< ComponentTypeID, std::unique_ptr< IComponentPool > > m_componentPools
void ValidateLevelPrefabs(const Olympe::Editor::LevelDefinition &levelDef)
void SetMapBounds(int minTileX, int minTileY, int maxTileX, int maxTileY, int chunkOriginX, int chunkOriginY)
TilesetManager m_tilesetManager
void Notify_ECS_Systems(EntityID entity, ComponentSignature signature)
T & GetComponent(EntityID entity)
std::unordered_map< EntityID, ComponentSignature > m_entitySignatures
RenderLayer CalculateLayerFromZOrder(float zOrder) const
Calculate layer index from zOrder value (for Tiled levels) Maps zOrder ranges to layer indices for pr...
RenderLayer GetEntityLayer(EntityID entity) const
Get entity render layer.
virtual ~World()
Destructor.
void GenerateCollisionAndNavigationMaps(const Olympe::Tiled::TiledMap &tiledMap, const Olympe::Editor::LevelDefinition &levelDef)
bool InstantiatePass2_SpatialStructure(const Olympe::Editor::LevelDefinition &levelDef, InstantiationResult &result)
float m_cachedIsometricOriginX
void RegisterPlayerEntity(EntityID entity)
Register a player entity that was loaded from a level file Validates required components and delegate...
float m_cachedIsometricOriginY
float GetIsometricOriginX() const
float GetIsometricOriginY() const
std::vector< std::unique_ptr< ECS_System > > m_systems
std::vector< EntityID > m_entities
void Process_ECS_Systems()
void RenderDebug_ECS_Systems()
std::vector< TileChunk > m_tileChunks
void Add_ECS_System(std::unique_ptr< ECS_System > system)
bool InstantiatePass5_Relationships(const Olympe::Editor::LevelDefinition &levelDef, InstantiationResult &result)
std::string m_mapOrientation
void SetEntityLayer(EntityID entity, RenderLayer layer)
Set entity render layer (updates position.z)
void DestroyEntity(EntityID entity)
World()
Default constructor.
void ExtractCustomProperties(const nlohmann::json &overrides, LevelInstanceParameters &instanceParams, const Olympe::Editor::EntityInstance *entityInstance=nullptr, const PrefabBlueprint *prefab=nullptr)
Extract custom properties from JSON overrides into LevelInstanceParameters.
LayerProperties ParseLayerProperties(const std::map< std::string, TiledProperty > &properties)
bool IsCollisionLayer(const std::shared_ptr< Olympe::Tiled::TiledLayer > &layer)
ComponentParameter JsonValueToComponentParameter(const nlohmann::json &value)
Header file for PrefabFactory class, responsible for creating game object prefabs.
static ComponentParameter FromBool(bool value)
static ComponentParameter FromFloat(float value)
static ComponentParameter FromVector3(float x, float y, float z)
static ComponentParameter FromInt(int value)
static ComponentParameter FromArray(const nlohmann::json &arrayData)
static ComponentParameter FromString(const std::string &value)
Identity component for entity identification.
std::vector< std::unique_ptr< EntityInstance > > entities
Position component for spatial location.
Represents a chunk of tiles for rendering.
std::string layerName
Name of the source layer.
Information about a loaded tileset.
int columns
Number of columns in atlas.
std::string name
Tileset name.
int tileoffsetX
Global X offset for all tiles.
SDL_Texture * texture
Atlas texture (image-based)
uint32_t firstgid
First Global ID in this tileset.
int spacing
Spacing between tiles.
int margin
Margin around atlas.
int tileheight
Height of each tile.
bool isCollection
True if collection tileset.
std::map< uint32_t, SDL_Texture * > individualTiles
Per-tile textures.
int tilewidth
Width of each tile.
std::map< uint32_t, SDL_Rect > individualSrcRects
Per-tile source rects.
std::vector< std::string > failedObjects