Olympe Engine 2.0
2D Game Engine with ECS Architecture
Loading...
Searching...
No Matches
PrefabFactory.cpp
Go to the documentation of this file.
1/*
2 Olympe Engine V2 - 2025
3 Nicolas Chereau
4 nchereau@gmail.com
5
6 Purpose:
7 - Implementation file for PrefabFactory class.
8 - Component-agnostic instantiation system.
9*/
10
11#include "prefabfactory.h"
12#include "ComponentRegistry.h"
13#include "ComponentDefinition.h"
14#include "PrefabScanner.h"
15#include "ParameterResolver.h"
16#include "World.h"
17#include "DataManager.h"
18#include "ECS_Components.h"
19#include "ECS_Components_AI.h"
21#include "system/system_utils.h"
22#include "AI/BehaviorTree.h"
23#include <string>
24#include <unordered_map>
25#include "VideoGame.h"
26
27// ========================================================================
28// Component Factory Registry Implementation
29// ========================================================================
30
32 std::function<bool(EntityID, const ComponentDefinition&)> factory)
33{
34 // Check if component is already registered (prevents duplicate registrations from multiple translation units)
36 {
37 // Already registered, silently ignore duplicate
38 return;
39 }
40
41 // First registration: store factory and log
43 std::cout << "[ComponentRegistry] Registered: " << componentName << "\n";
44}
45
47{
49}
50
51std::vector<std::string> PrefabFactory::GetRegisteredComponents() const
52{
53 std::vector<std::string> components;
54 components.reserve(m_componentFactories.size());
55 for (const auto& kv : m_componentFactories)
56 {
57 components.push_back(kv.first);
58 }
59 return components;
60}
61
62// Helper function for macro
68
69// ========================================================================
70// Public API Implementation
71// ========================================================================
72
74{
76 {
77 SYSTEM_LOG << "PrefabFactory::PreloadAllPrefabs: Already preloaded\n";
78 return;
79 }
80
81 SYSTEM_LOG << "+===========================================================+\n";
82 SYSTEM_LOG << "| PREFAB FACTORY: PRELOADING ALL PREFABS |\n";
83 SYSTEM_LOG << "+===========================================================+\n";
84
85 // Use new unified Initialize method from PrefabScanner
88
89 // Store scanner for type normalization
90 m_scanner = std::make_unique<PrefabScanner>(std::move(scanner));
91
92 int prefabCount = static_cast<int>(m_prefabRegistry.GetCount());
93
94 SYSTEM_LOG << "ok - Loaded " << prefabCount << " prefabs:\n";
95
97 for (const auto& name : allNames)
98 {
100 if (bp && bp->isValid)
101 {
102 SYSTEM_LOG << " +- " << name << " (" << bp->components.size() << " components)\n";
103 }
104 }
105
106 SYSTEM_LOG << "\nok - PrefabFactory ready\n\n";
107 m_prefabsPreloaded = true;
108}
109
111{
113 {
114 SYSTEM_LOG << "/!\\ PrefabFactory: Prefabs not preloaded! Call PreloadAllPrefabs() first\n";
115 return INVALID_ENTITY_ID;
116 }
117
118 const PrefabBlueprint* blueprint = m_prefabRegistry.Find(prefabName);
119
120 if (!blueprint || !blueprint->isValid)
121 {
122 SYSTEM_LOG << "x PrefabFactory: Prefab '" << prefabName << "' not found\n";
123 return INVALID_ENTITY_ID;
124 }
125
127}
128
129EntityID PrefabFactory::CreateEntity(const std::string& prefabName)
130{
131 // Try legacy system first
132 if (m_prefabs.find(prefabName) != m_prefabs.end())
133 {
135 m_prefabs[prefabName](newEntity);
136 SYSTEM_LOG << "PrefabFactory::CreateEntity '" << prefabName << "' created (ID: " << newEntity << ")\n";
137 return newEntity;
138 }
139
140 // Fallback to modern system
141 return CreateEntityFromPrefabName(prefabName);
142}
143
145{
147 SYSTEM_LOG << "PrefabFactory: Registry cached with " << registry.GetCount() << " prefabs\n";
148
149 // Mark as preloaded if registry is non-empty
150 if (registry.GetCount() > 0)
151 {
152 m_prefabsPreloaded = true;
153 }
154}
155
156std::string PrefabFactory::NormalizeType(const std::string& type) const
157{
158 if (m_scanner)
159 {
160 return m_scanner->NormalizeType(type);
161 }
162 return type;
163}
164
165bool PrefabFactory::AreTypesEquivalent(const std::string& type1, const std::string& type2) const
166{
167 if (m_scanner)
168 {
169 return m_scanner->AreTypesEquivalent(type1, type2);
170 }
171 return type1 == type2;
172}
173
174bool PrefabFactory::IsTypeRegistered(const std::string& type) const
175{
176 if (m_scanner)
177 {
178 return m_scanner->IsTypeRegistered(type);
179 }
180 return false;
181}
182
183bool PrefabFactory::GetCanonicalInfo(const std::string& type, std::string& outCanonical,
184 std::string& outPrefabFile) const
185{
186 if (m_scanner)
187 {
188 return m_scanner->GetCanonicalInfo(type, outCanonical, outPrefabFile);
189 }
190 return false;
191}
192
194{
195 if (!blueprint.isValid)
196 {
197 SYSTEM_LOG << "PrefabFactory::CreateEntityFromBlueprint: Invalid blueprint '"
198 << blueprint.prefabName << "'\n";
199 return INVALID_ENTITY_ID;
200 }
201
202 // Create entity
203 World& world = World::Get();
204 EntityID entity = world.CreateEntity();
205
206 if (entity == INVALID_ENTITY_ID)
207 {
208 SYSTEM_LOG << "PrefabFactory::CreateEntityFromBlueprint: Failed to create entity for '"
209 << blueprint.prefabName << "'\n";
210 return INVALID_ENTITY_ID;
211 }
212
213 // Instantiate all components
214 int successCount = 0;
215 int failCount = 0;
216
217 for (const auto& componentDef : blueprint.components)
218 {
220 {
221 successCount++;
222 }
223 else
224 {
225 failCount++;
226 SYSTEM_LOG << "PrefabFactory::CreateEntityFromBlueprint: Failed to instantiate component '"
227 << componentDef.componentType << "' on entity " << entity << "\n";
228 }
229 }
230
231 // -> Auto-assign render layer based on entity type (if requested)
232 if (autoAssignLayer &&
233 world.HasComponent<Identity_data>(entity) &&
234 world.HasComponent<Position_data>(entity))
235 {
236 const Identity_data& identity = world.GetComponent<Identity_data>(entity);
238 world.SetEntityLayer(entity, defaultLayer);
239
240 }
241
242 return entity;
243}
244
248 bool autoAssignLayer)
249{
250 if (!blueprint.isValid)
251 {
252 SYSTEM_LOG << "PrefabFactory::CreateEntityWithOverrides: Invalid blueprint '"
253 << blueprint.prefabName << "'\n";
254 return INVALID_ENTITY_ID;
255 }
256
257 // Create entity
258 World& world = World::Get();
259 EntityID entity = world.CreateEntity();
260
261 if (entity == INVALID_ENTITY_ID)
262 {
263 SYSTEM_LOG << "PrefabFactory::CreateEntityWithOverrides: Failed to create entity for '"
264 << blueprint.prefabName << "'\n";
265 return INVALID_ENTITY_ID;
266 }
267
268 // Use ParameterResolver to merge prefab defaults with instance parameters
270 std::vector<ResolvedComponentInstance> resolvedComponents = resolver.Resolve(blueprint, instanceParams);
271
272 // Instantiate components with resolved parameters
273 // NOTE: If some components fail to instantiate, the entity is still returned with partial state.
274 // This is intentional - allows entities to be created even if some optional components fail.
275 // Callers should check component existence before accessing them.
276 int successCount = 0;
277 int failCount = 0;
278
279 for (const auto& resolved : resolvedComponents)
280 {
281 if (!resolved.isValid)
282 {
283 failCount++;
284 SYSTEM_LOG << " /!\\ Invalid resolved component: " << resolved.componentType << "\n";
285 continue;
286 }
287
289 compDef.componentType = resolved.componentType;
290 compDef.parameters = resolved.parameters;
291
292 if (InstantiateComponent(entity, compDef))
293 {
294 successCount++;
295 }
296 else
297 {
298 failCount++;
299 SYSTEM_LOG << " /!\\ Failed to instantiate component: " << resolved.componentType << "\n";
300 }
301 }
302
303 // Override position INCLUDING z component (zOrder) to preserve layer depth
304 if (world.HasComponent<Position_data>(entity))
305 {
306 auto& pos = world.GetComponent<Position_data>(entity);
307 pos.position = instanceParams.position;
308 }
309
310 // -> Auto-assign render layer based on entity type (if requested)
311 if (autoAssignLayer &&
312 world.HasComponent<Identity_data>(entity) &&
313 world.HasComponent<Position_data>(entity))
314 {
315 const Identity_data& identity = world.GetComponent<Identity_data>(entity);
317 world.SetEntityLayer(entity, defaultLayer);
318 }
319
320 SYSTEM_LOG << " -> Created with " << successCount << " components";
321 if (failCount > 0)
322 {
323 SYSTEM_LOG << " (" << failCount << " failed)";
324 }
325 SYSTEM_LOG << "\n";
326
327 return entity;
328}
329
331{
332 const std::string& type = componentDef.componentType;
333
334 // Step 1: Try auto-registered components first
335 auto it = m_componentFactories.find(type);
336 if (it != m_componentFactories.end())
337 {
338 // Call the registered factory function to create component
339 bool success = it->second(entity, componentDef);
340 if (!success)
341 {
342 return false;
343 }
344
345 // For components that need specialized parameter handling, call the specialized function
346 // Note: The specialized function applies parameters but does NOT recreate the component
347 // This if-else chain is intentional for clarity and ease of modification.
348 // Performance impact is negligible as this only runs once per component during entity creation.
349 if (type == "BehaviorTreeRuntime_data")
351 else if (type == "Position_data")
352 return InstantiatePosition(entity, componentDef);
353 else if (type == "Identity_data")
354 return InstantiateIdentity(entity, componentDef);
355 else if (type == "PhysicsBody_data")
356 return InstantiatePhysicsBody(entity, componentDef);
357 else if (type == "VisualSprite_data")
359 else if (type == "VisualAnimation_data")
361 else if (type == "AIBlackboard_data")
363 else if (type == "AISenses_data")
364 return InstantiateAISenses(entity, componentDef);
365 else if (type == "MoveIntent_data")
366 return InstantiateMoveIntent(entity, componentDef);
367 else if (type == "NavigationAgent_data")
369
370 // Component created successfully with default values
371 // too soon return true;
372 }
373
374 // Step 2: Fallback to legacy specialized functions (for backward compatibility)
375 // This allows the system to work even if AUTO_REGISTER_COMPONENT was forgotten
376 if (type == "Identity" || type == "Identity_data")
377 return InstantiateIdentity(entity, componentDef);
378 else if (type == "Position" || type == "Position_data")
379 return InstantiatePosition(entity, componentDef);
380 else if (type == "PhysicsBody" || type == "PhysicsBody_data")
381 return InstantiatePhysicsBody(entity, componentDef);
382 else if (type == "VisualSprite" || type == "VisualSprite_data")
384 else if (type == "VisualAnimation" || type == "VisualAnimation_data")
386 else if (type == "VisualEditor" || type == "VisualEditor_data")
388 else if (type == "AIBehavior" || type == "AIBehavior_data")
389 return InstantiateAIBehavior(entity, componentDef);
390 else if (type == "AIBlackboard" || type == "AIBlackboard_data")
392 else if (type == "AISenses" || type == "AISenses_data")
393 return InstantiateAISenses(entity, componentDef);
394 else if (type == "AIState" || type == "AIState_data")
395 return InstantiateAIState(entity, componentDef);
396 else if (type == "BehaviorTreeRuntime" || type == "BehaviorTreeRuntime_data")
398 else if (type == "MoveIntent" || type == "MoveIntent_data")
399 return InstantiateMoveIntent(entity, componentDef);
400 else if (type == "AttackIntent" || type == "AttackIntent_data")
402 else if (type == "BoundingBox" || type == "BoundingBox_data")
403 return InstantiateBoundingBox(entity, componentDef);
404 else if (type == "Movement" || type == "Movement_data")
405 return InstantiateMovement(entity, componentDef);
406 else if (type == "Health" || type == "Health_data")
407 return InstantiateHealth(entity, componentDef);
408 else if (type == "TriggerZone" || type == "TriggerZone_data")
409 return InstantiateTriggerZone(entity, componentDef);
410 else if (type == "CollisionZone" || type == "CollisionZone_data")
412 else if (type == "Animation" || type == "Animation_data")
413 return InstantiateAnimation(entity, componentDef);
414 else if (type == "FX" || type == "FX_data")
415 return InstantiateFX(entity, componentDef);
416 else if (type == "AudioSource" || type == "AudioSource_data")
417 return InstantiateAudioSource(entity, componentDef);
418 else if (type == "Controller" || type == "Controller_data")
419 return InstantiateController(entity, componentDef);
420 else if (type == "PlayerController" || type == "PlayerController_data")
422 else if (type == "PlayerBinding" || type == "PlayerBinding_data")
424 else if (type == "NPC" || type == "NPC_data")
425 return InstantiateNPC(entity, componentDef);
426 else if (type == "Inventory" || type == "Inventory_data")
427 return InstantiateInventory(entity, componentDef);
428 else if (type == "Camera" || type == "Camera_data")
429 return InstantiateCamera(entity, componentDef);
430 else if (type == "CameraTarget" || type == "CameraTarget_data")
432 else if (type == "CameraEffects" || type == "CameraEffects_data")
434 else if (type == "CameraBounds" || type == "CameraBounds_data")
436 else if (type == "CameraInputBinding" || type == "CameraInputBinding_data")
438 else if (type == "InputMapping" || type == "InputMapping_data")
440 else
441 {
442 SYSTEM_LOG << "PrefabFactory::InstantiateComponent: Unknown component type '"
443 << type << "'\n";
444 SYSTEM_LOG << " Available auto-registered components:\n";
445 for (const auto& kv : m_componentFactories)
446 {
447 SYSTEM_LOG << " - " << kv.first << "\n";
448 }
449 return false;
450 }
451
452}
453
454// ========================================================================
455// Component-specific instantiation helpers
456// ========================================================================
457
458// Helper function to convert string to EntityType enum
459static EntityType StringToEntityType(const std::string& typeStr)
460{
461 static const std::unordered_map<std::string, EntityType> typeMap = {
462 {"Player", EntityType::Player},
463 {"NPC", EntityType::NPC},
464 {"Enemy", EntityType::Enemy},
465 {"Item", EntityType::Item},
466 {"Collectible", EntityType::Collectible},
467 {"Effect", EntityType::Effect},
468 {"Particle", EntityType::Particle},
469 {"UIElement", EntityType::UIElement},
470 {"Background", EntityType::Background},
471 {"Trigger", EntityType::Trigger},
472 {"Waypoint", EntityType::Waypoint},
473 {"Static", EntityType::Static},
474 {"Dynamic", EntityType::Dynamic}
475 };
476
477 auto it = typeMap.find(typeStr);
478 return (it != typeMap.end()) ? it->second : EntityType::None;
479}
480
482{
483 // Get the EXISTING component created by auto-registration
485 {
486 std::cerr << "[PrefabFactory] ERROR: Identity_data not found for entity " << entity << std::endl;
487 std::cerr << "[PrefabFactory] This should have been created by auto-registration!" << std::endl;
488 return false;
489 }
490
491 // Get reference to existing component (not a copy)
493
494 // Extract parameters
495 if (def.HasParameter("name"))
496 identity.name = def.GetParameter("name")->AsString();
497
498 if (def.HasParameter("tag"))
499 identity.tag = def.GetParameter("tag")->AsString();
500
501 if (def.HasParameter("entityType"))
502 {
503 // Store string type for backward compatibility
504 identity.type = def.GetParameter("entityType")->AsString();
505
506 // Map string to EntityType enum using helper function
507 identity.entityType = StringToEntityType(identity.type);
508 }
509
510 // DO NOT call AddComponent() - component is already modified by reference
511 return true;
512}
513
515{
516 // Get the EXISTING component created by auto-registration
518 {
519 std::cerr << "[PrefabFactory] ERROR: Position_data not found for entity " << entity << std::endl;
520 std::cerr << "[PrefabFactory] This should have been created by auto-registration!" << std::endl;
521 return false;
522 }
523
524 // Get reference to existing component (not a copy)
525 Position_data& position = World::Get().GetComponent<Position_data>(entity);
526
527 // Extract position vector
528 if (def.HasParameter("position"))
529 {
530 position.position = def.GetParameter("position")->AsVector();
531 }
532 else if (def.HasParameter("x") && def.HasParameter("y"))
533 {
534 float x = def.GetParameter("x")->AsFloat();
535 float y = def.GetParameter("y")->AsFloat();
536 float z = def.HasParameter("z") ? def.GetParameter("z")->AsFloat() : 0.0f;
537 position.position = Vector(x, y, z);
538 }
539
540 // DO NOT call AddComponent() - component is already modified by reference
541 return true;
542}
543
545{
546 // Get the EXISTING component created by auto-registration
548 {
549 std::cerr << "[PrefabFactory] ERROR: PhysicsBody_data not found for entity " << entity << std::endl;
550 std::cerr << "[PrefabFactory] This should have been created by auto-registration!" << std::endl;
551 return false;
552 }
553
554 // Get reference to existing component (not a copy)
556
557 // Extract parameters
558 if (def.HasParameter("mass"))
559 physics.mass = def.GetParameter("mass")->AsFloat();
560
561 if (def.HasParameter("speed"))
562 physics.speed = def.GetParameter("speed")->AsFloat();
563
564 // REQUIREMENT E: Apply friction, useGravity, and rotation when present
565 if (def.HasParameter("friction"))
566 physics.friction = def.GetParameter("friction")->AsFloat();
567
568 if (def.HasParameter("useGravity"))
569 physics.useGravity = def.GetParameter("useGravity")->AsBool();
570
571 if (def.HasParameter("rotation"))
572 physics.rotation = def.GetParameter("rotation")->AsFloat();
573
574 // DO NOT call AddComponent() - component is already modified by reference
575 return true;
576}
577
579{
580 // Get the EXISTING component created by auto-registration
582 {
583 std::cerr << "[PrefabFactory] ERROR: VisualSprite_data not found for entity " << entity << std::endl;
584 std::cerr << "[PrefabFactory] This should have been created by auto-registration!" << std::endl;
585 return false;
586 }
587
588 // Get reference to existing component (not a copy)
590
591 // Extract sprite path and load sprite
592 if (def.HasParameter("spritePath"))
593 {
594 std::string spritePath = def.GetParameter("spritePath")->AsString();
595
596 // Load sprite via DataManager
598
599 if (!visual.sprite)
600 {
601 SYSTEM_LOG << "PrefabFactory::InstantiateVisualSprite: Failed to load sprite '"
602 << spritePath << "' - component will have null sprite\n";
603 // Don't fail completely - create component with null sprite
604 }
605 else
606 {
607 // Get texture dimensions for srcRect
608 float texW, texH;
610
611 // Extract optional srcRect
612 if (def.HasParameter("srcX") && def.HasParameter("srcY") &&
613 def.HasParameter("srcW") && def.HasParameter("srcH"))
614 {
615 visual.srcRect.x = def.GetParameter("srcX")->AsFloat();
616 visual.srcRect.y = def.GetParameter("srcY")->AsFloat();
617 visual.srcRect.w = def.GetParameter("srcW")->AsFloat();
618 visual.srcRect.h = def.GetParameter("srcH")->AsFloat();
619 }
620 else
621 {
622 // Default to full texture
623 visual.srcRect = SDL_FRect{0, 0, texW, texH};
624 }
625
626 // Extract optional hotSpot
627 if (def.HasParameter("hotSpot"))
628 {
629 visual.hotSpot = def.GetParameter("hotSpot")->AsVector();
630 }
631 else if (def.HasParameter("hotSpotX") && def.HasParameter("hotSpotY"))
632 {
633 float x = def.GetParameter("hotSpotX")->AsFloat();
634 float y = def.GetParameter("hotSpotY")->AsFloat();
635 visual.hotSpot = Vector(x, y, 0.0f);
636 }
637 else
638 {
639 // Default to center of sprite
640 visual.hotSpot = Vector(texW / 2.0f, texH / 2.0f, 0.0f);
641 }
642 }
643 }
644
645 // Extract optional color
646 if (def.HasParameter("color"))
647 {
648 visual.color = def.GetParameter("color")->AsColor();
649 }
650
651 // REQUIREMENT E: Apply visible parameter when explicitly provided
652 if (def.HasParameter("visible"))
653 {
654 visual.visible = def.GetParameter("visible")->AsBool();
655 }
656
657 // NOTE: width/height/layer fields don't exist in VisualSprite_data struct yet
658 // These parameters are validated by schema but not applied until struct is updated
659 // For now, srcRect.w and srcRect.h serve as the effective width/height
660
661 // DO NOT call AddComponent() - component is already modified by reference
662 return true;
663}
664
666{
668
669 // Extract sprite path and load sprite
670 if (def.HasParameter("spritePath"))
671 {
672 std::string spritePath = def.GetParameter("spritePath")->AsString();
673
674 // Load sprite via DataManager
676
677 if (!editor.sprite)
678 {
679 SYSTEM_LOG << "PrefabFactory::InstantiateVisualEditor: Failed to load sprite '"
680 << spritePath << "' - component will have null sprite\n";
681 // Don't fail completely - create component with null sprite
682 }
683 else
684 {
685 // Get texture dimensions for srcRect
686 float texW, texH;
688
689 // Set srcRect to full texture dimensions
690 editor.srcRect = SDL_FRect{0, 0, texW, texH};
691
692 // Set hotSpot to center of sprite
693 editor.hotSpot = Vector(texW / 2.0f, texH / 2.0f, 0.0f);
694 }
695 }
696
697 // Extract optional color
698 if (def.HasParameter("color"))
699 {
700 editor.color = def.GetParameter("color")->AsColor();
701 }
702 else
703 {
704 // Default to white
705 editor.color = SDL_Color{255, 255, 255, 255};
706 }
707
708 // Extract optional visibility flag
709 if (def.HasParameter("visible"))
710 {
711 editor.isVisible = def.GetParameter("visible")->AsBool();
712 }
713 else
714 {
715 // Default to visible
716 editor.isVisible = true;
717 }
718
719 // REQUIREMENT E: Apply layer when explicitly provided (if VisualEditor_data had the field)
720 // NOTE: width/height/layer fields don't exist in VisualEditor_data struct yet
721 // These parameters are validated by schema but not applied until struct is updated
722
724 return true;
725}
726
728{
729 // Get the EXISTING component created by auto-registration
731 {
732 std::cerr << "[PrefabFactory] ERROR: VisualAnimation_data not found for entity " << entity << std::endl;
733 std::cerr << "[PrefabFactory] This should have been created by auto-registration!" << std::endl;
734 return false;
735 }
736
737 // Get reference to existing component (not a copy)
739
740 // Extract animation bank reference
741 if (def.HasParameter("bankId"))
742 animData.bankId = def.GetParameter("bankId")->AsString();
743
744 // Extract current animation name
745 if (def.HasParameter("currentAnimName"))
746 animData.currentAnimName = def.GetParameter("currentAnimName")->AsString();
747
748 // Extract optional animation graph path
749 if (def.HasParameter("animGraphPath"))
750 animData.animGraphPath = def.GetParameter("animGraphPath")->AsString();
751
752 // Extract playback settings
753 if (def.HasParameter("playbackSpeed"))
754 animData.playbackSpeed = def.GetParameter("playbackSpeed")->AsFloat();
755
756 if (def.HasParameter("isPlaying"))
757 animData.isPlaying = def.GetParameter("isPlaying")->AsBool();
758
759 if (def.HasParameter("isPaused"))
760 animData.isPaused = def.GetParameter("isPaused")->AsBool();
761
762 if (def.HasParameter("loop"))
763 animData.loop = def.GetParameter("loop")->AsBool();
764
765 // Extract visual transforms
766 if (def.HasParameter("flipX"))
767 animData.flipX = def.GetParameter("flipX")->AsBool();
768
769 if (def.HasParameter("flipY"))
770 animData.flipY = def.GetParameter("flipY")->AsBool();
771
772 // DO NOT call AddComponent() - component is already modified by reference
773 return true;
774}
775
777{
779
780 // Extract behavior type
781 if (def.HasParameter("behaviorType"))
782 ai.behaviorType = def.GetParameter("behaviorType")->AsString();
783
785 return true;
786}
787
789{
790 // Get the EXISTING component created by auto-registration
792 {
793 std::cerr << "[PrefabFactory] ERROR: AIBlackboard_data not found for entity " << entity << std::endl;
794 std::cerr << "[PrefabFactory] This should have been created by auto-registration!" << std::endl;
795 return false;
796 }
797
798 // Get reference to existing component (not a copy)
800
801 // Extract blackboard parameters
802 if (def.HasParameter("targetEntity"))
803 blackboard.targetEntity = def.GetParameter("targetEntity")->AsEntityRef();
804
805 if (def.HasParameter("hasTarget"))
806 blackboard.hasTarget = def.GetParameter("hasTarget")->AsBool();
807
808 if (def.HasParameter("attackCooldown"))
809 blackboard.attackCooldown = def.GetParameter("attackCooldown")->AsFloat();
810
811 // Add support for additional AI parameters
812 if (def.HasParameter("distanceToTarget"))
813 blackboard.distanceToTarget = def.GetParameter("distanceToTarget")->AsFloat();
814
815 if (def.HasParameter("targetVisible"))
816 blackboard.targetVisible = def.GetParameter("targetVisible")->AsBool();
817
818 if (def.HasParameter("targetInRange"))
819 blackboard.targetInRange = def.GetParameter("targetInRange")->AsBool();
820
821 // DO NOT call AddComponent() - component is already modified by reference
822 return true;
823}
824
826{
827 // Get the EXISTING component created by auto-registration
829 {
830 std::cerr << "[PrefabFactory] ERROR: AISenses_data not found for entity " << entity << std::endl;
831 std::cerr << "[PrefabFactory] This should have been created by auto-registration!" << std::endl;
832 return false;
833 }
834
835 // Get reference to existing component (not a copy)
837
838 // Extract senses parameters
839 if (def.HasParameter("visionRadius"))
840 senses.visionRadius = def.GetParameter("visionRadius")->AsFloat();
841 else if (def.HasParameter("visionRange"))
842 senses.visionRadius = def.GetParameter("visionRange")->AsFloat();
843
844 if (def.HasParameter("visionAngle"))
845 senses.visionAngle = def.GetParameter("visionAngle")->AsFloat();
846
847 if (def.HasParameter("hearingRadius"))
848 senses.hearingRadius = def.GetParameter("hearingRadius")->AsFloat();
849 else if (def.HasParameter("hearingRange"))
850 senses.hearingRadius = def.GetParameter("hearingRange")->AsFloat();
851
852 if (def.HasParameter("perceptionHz"))
853 senses.perceptionHz = def.GetParameter("perceptionHz")->AsFloat();
854
855 if (def.HasParameter("thinkHz"))
856 senses.thinkHz = def.GetParameter("thinkHz")->AsFloat();
857
858 // DO NOT call AddComponent() - component is already modified by reference
859 return true;
860}
861
863{
865
866 // Extract width and height
867 if (def.HasParameter("width") && def.HasParameter("height"))
868 {
869 bbox.boundingBox.w = def.GetParameter("width")->AsFloat();
870 bbox.boundingBox.h = def.GetParameter("height")->AsFloat();
871
872 // Optional x, y offset
873 if (def.HasParameter("x"))
874 bbox.boundingBox.x = def.GetParameter("x")->AsFloat();
875 if (def.HasParameter("y"))
876 bbox.boundingBox.y = def.GetParameter("y")->AsFloat();
877
878 // Optional offsetX, offsetY (alternative to x,y)
879 if (def.HasParameter("offsetX"))
880 bbox.boundingBox.x = def.GetParameter("offsetX")->AsFloat();
881 if (def.HasParameter("offsetY"))
882 bbox.boundingBox.y = def.GetParameter("offsetY")->AsFloat();
883 }
884
886 return true;
887}
888
890{
892
893 // Extract direction
894 if (def.HasParameter("direction"))
895 {
896 movement.direction = def.GetParameter("direction")->AsVector();
897 }
898 else if (def.HasParameter("directionX") && def.HasParameter("directionY"))
899 {
900 float x = def.GetParameter("directionX")->AsFloat();
901 float y = def.GetParameter("directionY")->AsFloat();
902 movement.direction = Vector(x, y, 0.0f);
903 }
904
905 // Extract velocity
906 if (def.HasParameter("velocity"))
907 {
908 movement.velocity = def.GetParameter("velocity")->AsVector();
909 }
910 else if (def.HasParameter("velocityX") && def.HasParameter("velocityY"))
911 {
912 float x = def.GetParameter("velocityX")->AsFloat();
913 float y = def.GetParameter("velocityY")->AsFloat();
914 movement.velocity = Vector(x, y, 0.0f);
915 }
916
918 return true;
919}
920
922{
924
925 // Extract health parameters
926 if (def.HasParameter("currentHealth"))
927 health.currentHealth = def.GetParameter("currentHealth")->AsInt();
928
929 if (def.HasParameter("maxHealth"))
930 health.maxHealth = def.GetParameter("maxHealth")->AsInt();
931
932
934 return true;
935}
936
938{
940
941 // Extract radius
942 if (def.HasParameter("radius"))
943 trigger.radius = def.GetParameter("radius")->AsFloat();
944
945 if (def.HasParameter("triggered"))
946 trigger.triggered = def.GetParameter("triggered")->AsBool();
947
949 return true;
950}
951
953{
954 CollisionZone_data collision;
955
956 // Extract bounds
957 if (def.HasParameter("x") && def.HasParameter("y") &&
958 def.HasParameter("width") && def.HasParameter("height"))
959 {
960 collision.bounds.x = def.GetParameter("x")->AsFloat();
961 collision.bounds.y = def.GetParameter("y")->AsFloat();
962 collision.bounds.w = def.GetParameter("width")->AsFloat();
963 collision.bounds.h = def.GetParameter("height")->AsFloat();
964 }
965
966 if (def.HasParameter("isStatic"))
967 collision.isStatic = def.GetParameter("isStatic")->AsBool();
968
969 World::Get().AddComponent<CollisionZone_data>(entity, collision);
970 return true;
971}
972
974{
975 Animation_data animation;
976
977 // Extract animation parameters
978 if (def.HasParameter("animationID"))
979 animation.animationID = def.GetParameter("animationID")->AsString();
980
981 if (def.HasParameter("frameDuration"))
982 animation.frameDuration = def.GetParameter("frameDuration")->AsFloat();
983
984 if (def.HasParameter("currentFrame"))
985 animation.currentFrame = def.GetParameter("currentFrame")->AsInt();
986
987 World::Get().AddComponent<Animation_data>(entity, animation);
988 return true;
989}
990
992{
993 FX_data fx;
994
995 // Extract FX parameters
996 if (def.HasParameter("effectType"))
997 fx.effectType = def.GetParameter("effectType")->AsString();
998
999 if (def.HasParameter("duration"))
1000 fx.duration = def.GetParameter("duration")->AsFloat();
1001
1002 World::Get().AddComponent<FX_data>(entity, fx);
1003 return true;
1004}
1005
1007{
1008 AudioSource_data audio;
1009
1010 // Extract audio parameters
1011 if (def.HasParameter("soundEffectID"))
1012 audio.soundEffectID = def.GetParameter("soundEffectID")->AsString();
1013
1014 if (def.HasParameter("volume"))
1015 audio.volume = def.GetParameter("volume")->AsFloat();
1016
1017 World::Get().AddComponent<AudioSource_data>(entity, audio);
1018 return true;
1019}
1020
1022{
1024
1025 // Extract controller parameters
1026 if (def.HasParameter("controllerID"))
1027 controller.controllerID = static_cast<short>(def.GetParameter("controllerID")->AsInt());
1028 else
1029 {
1030 controller.controllerID = -1;
1031 }
1032
1033
1034 if (def.HasParameter("isConnected"))
1035 controller.isConnected = def.GetParameter("isConnected")->AsBool();
1036
1038 return true;
1039}
1040
1042{
1044
1045 // Extract player controller parameters
1046 if (def.HasParameter("isJumping"))
1047 playerCtrl.isJumping = def.GetParameter("isJumping")->AsBool();
1048
1049 if (def.HasParameter("isShooting"))
1050 playerCtrl.isShooting = def.GetParameter("isShooting")->AsBool();
1051
1052 if (def.HasParameter("isRunning"))
1053 playerCtrl.isRunning = def.GetParameter("isRunning")->AsBool();
1054
1055 if (def.HasParameter("isInteracting"))
1056 playerCtrl.isInteracting = def.GetParameter("isInteracting")->AsBool();
1057
1058 if (def.HasParameter("isWalking"))
1059 playerCtrl.isWalking = def.GetParameter("isWalking")->AsBool();
1060
1061 if (def.HasParameter("isUsingItem"))
1062 playerCtrl.isUsingItem = def.GetParameter("isUsingItem")->AsBool();
1063
1064 if (def.HasParameter("isMenuOpen"))
1065 playerCtrl.isMenuOpen = def.GetParameter("isMenuOpen")->AsBool();
1066
1068 return true;
1069}
1070
1072{
1074
1075 // Extract binding parameters
1076 if (def.HasParameter("playerIndex"))
1077 binding.playerIndex = static_cast<short>(def.GetParameter("playerIndex")->AsInt());
1078
1079 if (def.HasParameter("controllerID"))
1080 binding.controllerID = static_cast<short>(def.GetParameter("controllerID")->AsInt());
1081
1083
1084 return true;
1085}
1086
1088{
1089 NPC_data npc;
1090
1091 // Extract NPC type
1092 if (def.HasParameter("npcType"))
1093 npc.npcType = def.GetParameter("npcType")->AsString();
1094
1095 World::Get().AddComponent<NPC_data>(entity, npc);
1096 return true;
1097}
1098
1100{
1102
1103 // Note: Items are typically added dynamically during gameplay
1104 // We don't extract items from the definition here
1105
1107 return true;
1108}
1109
1111{
1113
1114 // Extract camera parameters
1115 if (def.HasParameter("playerId"))
1116 camera.playerId = static_cast<short>(def.GetParameter("playerId")->AsInt());
1117
1118 if (def.HasParameter("zoom"))
1119 camera.zoom = def.GetParameter("zoom")->AsFloat();
1120
1121 if (def.HasParameter("targetZoom"))
1122 camera.targetZoom = def.GetParameter("targetZoom")->AsFloat();
1123
1124 if (def.HasParameter("position"))
1125 camera.position = def.GetParameter("position")->AsVector();
1126
1128 return true;
1129}
1130
1132{
1134
1135 // Extract target parameters
1136 if (def.HasParameter("targetEntityID"))
1137 target.targetEntityID = def.GetParameter("targetEntityID")->AsEntityRef();
1138
1139 if (def.HasParameter("followTarget"))
1140 target.followTarget = def.GetParameter("followTarget")->AsBool();
1141
1142 if (def.HasParameter("smoothFactor"))
1143 target.smoothFactor = def.GetParameter("smoothFactor")->AsFloat();
1144
1146 return true;
1147}
1148
1150{
1152
1153 // Extract effects parameters
1154 if (def.HasParameter("isShaking"))
1155 effects.isShaking = def.GetParameter("isShaking")->AsBool();
1156
1157 if (def.HasParameter("shakeIntensity"))
1158 effects.shakeIntensity = def.GetParameter("shakeIntensity")->AsFloat();
1159
1160 if (def.HasParameter("shakeDuration"))
1161 effects.shakeDuration = def.GetParameter("shakeDuration")->AsFloat();
1162
1164 return true;
1165}
1166
1168{
1169 CameraBounds_data bounds;
1170
1171 // Extract bounds parameters
1172 if (def.HasParameter("useBounds"))
1173 bounds.useBounds = def.GetParameter("useBounds")->AsBool();
1174
1175 if (def.HasParameter("x") && def.HasParameter("y") &&
1176 def.HasParameter("width") && def.HasParameter("height"))
1177 {
1178 bounds.boundingBox.x = def.GetParameter("x")->AsFloat();
1179 bounds.boundingBox.y = def.GetParameter("y")->AsFloat();
1180 bounds.boundingBox.w = def.GetParameter("width")->AsFloat();
1181 bounds.boundingBox.h = def.GetParameter("height")->AsFloat();
1182 }
1183
1184 World::Get().AddComponent<CameraBounds_data>(entity, bounds);
1185 return true;
1186}
1187
1189{
1191
1192 // Extract input binding parameters
1193 if (def.HasParameter("playerId"))
1194 binding.playerId = static_cast<short>(def.GetParameter("playerId")->AsInt());
1195
1196 if (def.HasParameter("useKeyboard"))
1197 binding.useKeyboard = def.GetParameter("useKeyboard")->AsBool();
1198
1199 if (def.HasParameter("deadzone"))
1200 binding.deadzone = def.GetParameter("deadzone")->AsFloat();
1201
1203 return true;
1204}
1205
1207{
1209
1210 // Initialize with defaults
1212
1213 // Extract custom parameters if provided
1214 if (def.HasParameter("deadzone"))
1215 mapping.deadzone = def.GetParameter("deadzone")->AsFloat();
1216
1217 if (def.HasParameter("sensitivity"))
1218 mapping.sensitivity = def.GetParameter("sensitivity")->AsFloat();
1219
1221 return true;
1222}
1223
1225{
1226 // Get existing component created by auto-registration
1228 {
1229 SYSTEM_LOG << "[PrefabFactory] ERROR: NavigationAgent_data should exist (auto-registration)\n";
1230 return false;
1231 }
1232
1234
1235 // Apply parameters
1236 if (def.HasParameter("agentRadius"))
1237 navAgent.agentRadius = def.GetParameter("agentRadius")->AsFloat();
1238
1239 if (def.HasParameter("maxSpeed"))
1240 navAgent.maxSpeed = def.GetParameter("maxSpeed")->AsFloat();
1241
1242 if (def.HasParameter("layerMask"))
1243 navAgent.layerMask = static_cast<int>(def.GetParameter("layerMask")->AsInt());
1244
1245 return true;
1246}
1247
1249{
1251
1252 // Extract AI state parameters
1253 if (def.HasParameter("currentState"))
1254 {
1255 std::string stateStr = def.GetParameter("currentState")->AsString();
1256 // Convert string to AIMode enum
1257 if (stateStr == "Idle") aiState.currentMode = AIMode::Idle;
1258 else if (stateStr == "Patrol") aiState.currentMode = AIMode::Patrol;
1259 else if (stateStr == "Combat") aiState.currentMode = AIMode::Combat;
1260 else if (stateStr == "Flee") aiState.currentMode = AIMode::Flee;
1261 else if (stateStr == "Investigate") aiState.currentMode = AIMode::Investigate;
1262 else if (stateStr == "Dead") aiState.currentMode = AIMode::Dead;
1263 else {
1264 SYSTEM_LOG << "PrefabFactory::InstantiateAIState: Warning - Unknown state '"
1265 << stateStr << "', defaulting to Idle\n";
1266 }
1267 }
1268
1269 if (def.HasParameter("previousState"))
1270 {
1271 std::string stateStr = def.GetParameter("previousState")->AsString();
1272 if (stateStr == "Idle") aiState.previousMode = AIMode::Idle;
1273 else if (stateStr == "Patrol") aiState.previousMode = AIMode::Patrol;
1274 else if (stateStr == "Combat") aiState.previousMode = AIMode::Combat;
1275 else if (stateStr == "Flee") aiState.previousMode = AIMode::Flee;
1276 else if (stateStr == "Investigate") aiState.previousMode = AIMode::Investigate;
1277 else if (stateStr == "Dead") aiState.previousMode = AIMode::Dead;
1278 else {
1279 SYSTEM_LOG << "PrefabFactory::InstantiateAIState: Warning - Unknown previousState '"
1280 << stateStr << "', defaulting to Idle\n";
1281 }
1282 }
1283
1284 if (def.HasParameter("combatEngageDistance"))
1285 aiState.combatEngageDistance = def.GetParameter("combatEngageDistance")->AsFloat();
1286
1287 if (def.HasParameter("fleeHealthThreshold"))
1288 aiState.fleeHealthThreshold = def.GetParameter("fleeHealthThreshold")->AsFloat();
1289
1290 if (def.HasParameter("investigateTimeout"))
1291 aiState.investigateTimeout = def.GetParameter("investigateTimeout")->AsFloat();
1292
1294 return true;
1295}
1296
1298{
1299 // Get the EXISTING component created by auto-registration
1301 {
1302 std::cerr << "[PrefabFactory] ERROR: BehaviorTreeRuntime_data not found for entity " << entity << std::endl;
1303 std::cerr << "[PrefabFactory] This should have been created by auto-registration!" << std::endl;
1304 return false;
1305 }
1306
1307 // Get reference to existing component (not a copy)
1309
1310 // Extract behavior tree runtime parameters
1311 // Support both old and new property names for backward compatibility
1312
1313 // Check for treeAssetId (old) or AITreeAssetId (new)
1314 if (def.HasParameter("AITreeAssetId"))
1315 {
1316 btRuntime.AITreeAssetId = static_cast<uint32_t>(def.GetParameter("AITreeAssetId")->AsInt());
1317 std::cerr << "[PrefabFactory] Entity " << entity << " AITreeAssetId set to " << btRuntime.AITreeAssetId << std::endl;
1318 }
1319 else if (def.HasParameter("treeAssetId"))
1320 {
1321 btRuntime.AITreeAssetId = static_cast<uint32_t>(def.GetParameter("treeAssetId")->AsInt());
1322 std::cerr << "[PrefabFactory] Entity " << entity << " treeAssetId (old) set to " << btRuntime.AITreeAssetId << std::endl;
1323 }
1324
1325 // Check for treePath (old) or AITreePath (new)
1326 std::string treePath;
1327 if (def.HasParameter("AITreePath"))
1328 {
1329 treePath = def.GetParameter("AITreePath")->AsString();
1330 }
1331 else if (def.HasParameter("treePath"))
1332 {
1333 treePath = def.GetParameter("treePath")->AsString();
1334 }
1335
1336 if (!treePath.empty())
1337 {
1338 Identity_data* identity = nullptr;
1339 if (World::Get().HasComponent<Identity_data>(entity))
1341
1342 // Map treePath -> treeId using the registry
1343 btRuntime.AITreePath = treePath;
1344
1346 btRuntime.AITreeAssetId = treeId;
1347
1348 if (identity != nullptr)
1349 std::cerr << "[PrefabFactory] Mapped BehaviorTree: " << treePath << " -> ID " << treeId << " for entity " << identity->name << std::endl;
1350 else
1351 std::cerr << "[PrefabFactory] Mapped BehaviorTree: " << treePath << " -> ID " << treeId << " for entity " << entity << std::endl;
1352
1353 // Verify the tree is loaded
1355 if (!tree)
1356 {
1357 std::cerr << "[PrefabFactory] WARNING: BehaviorTree not loaded: " << treePath
1358 << " (ID=" << treeId << ") - this should not happen if dependencies were loaded correctly" << std::endl;
1359 }
1360 }
1361
1362 if (def.HasParameter("active"))
1363 btRuntime.isActive = def.GetParameter("active")->AsBool();
1364
1365 // Support both old and new property names for currentNodeIndex
1366 if (def.HasParameter("AICurrentNodeIndex"))
1367 btRuntime.AICurrentNodeIndex = static_cast<uint32_t>(def.GetParameter("AICurrentNodeIndex")->AsInt());
1368 else if (def.HasParameter("currentNodeIndex"))
1369 btRuntime.AICurrentNodeIndex = static_cast<uint32_t>(def.GetParameter("currentNodeIndex")->AsInt());
1370
1371 // DO NOT call AddComponent() - component is already modified by reference
1372 return true;
1373}
1374
1376{
1377 // Get the EXISTING component created by auto-registration
1379 {
1380 std::cerr << "[PrefabFactory] ERROR: MoveIntent_data not found for entity " << entity << std::endl;
1381 std::cerr << "[PrefabFactory] This should have been created by auto-registration!" << std::endl;
1382 return false;
1383 }
1384
1385 // Get reference to existing component (not a copy)
1387
1388 // Extract move intent parameters
1389 if (def.HasParameter("targetX") && def.HasParameter("targetY"))
1390 {
1391 float x = def.GetParameter("targetX")->AsFloat();
1392 float y = def.GetParameter("targetY")->AsFloat();
1393 moveIntent.targetPosition = Vector(x, y, 0.0f);
1394 }
1395
1396 if (def.HasParameter("targetPosition"))
1397 moveIntent.targetPosition = def.GetParameter("targetPosition")->AsVector();
1398
1399 if (def.HasParameter("desiredSpeed"))
1400 moveIntent.desiredSpeed = def.GetParameter("desiredSpeed")->AsFloat();
1401
1402 if (def.HasParameter("hasTarget"))
1403 moveIntent.hasIntent = def.GetParameter("hasTarget")->AsBool();
1404
1405 if (def.HasParameter("hasIntent"))
1406 moveIntent.hasIntent = def.GetParameter("hasIntent")->AsBool();
1407
1408 if (def.HasParameter("arrivalThreshold"))
1409 moveIntent.arrivalThreshold = def.GetParameter("arrivalThreshold")->AsFloat();
1410
1411 if (def.HasParameter("usePathfinding"))
1412 moveIntent.usePathfinding = def.GetParameter("usePathfinding")->AsBool();
1413
1414 if (def.HasParameter("avoidObstacles"))
1415 moveIntent.avoidObstacles = def.GetParameter("avoidObstacles")->AsBool();
1416
1417 // DO NOT call AddComponent() - component is already modified by reference
1418 return true;
1419}
1420
1422{
1424
1425 // Extract attack intent parameters
1426 if (def.HasParameter("targetEntity"))
1427 attackIntent.targetEntity = def.GetParameter("targetEntity")->AsEntityRef();
1428
1429 if (def.HasParameter("targetPosition"))
1430 attackIntent.targetPosition = def.GetParameter("targetPosition")->AsVector();
1431
1432 if (def.HasParameter("damage"))
1433 attackIntent.damage = def.GetParameter("damage")->AsFloat();
1434
1435 if (def.HasParameter("range"))
1436 attackIntent.range = def.GetParameter("range")->AsFloat();
1437
1438 if (def.HasParameter("attackRange"))
1439 attackIntent.range = def.GetParameter("attackRange")->AsFloat();
1440
1441 if (def.HasParameter("hasIntent"))
1442 attackIntent.hasIntent = def.GetParameter("hasIntent")->AsBool();
1443
1444 if (def.HasParameter("cooldown"))
1445 attackIntent.cooldown = def.GetParameter("cooldown")->AsFloat();
1446
1447 if (def.HasParameter("attackType"))
1448 {
1449 std::string typeStr = def.GetParameter("attackType")->AsString();
1450 if (typeStr == "Melee") attackIntent.attackType = AttackIntent_data::AttackType::Melee;
1451 else if (typeStr == "Ranged") attackIntent.attackType = AttackIntent_data::AttackType::Ranged;
1452 else if (typeStr == "Area") attackIntent.attackType = AttackIntent_data::AttackType::Area;
1453 else {
1454 SYSTEM_LOG << "PrefabFactory::InstantiateAttackIntent: Warning - Unknown attackType '"
1455 << typeStr << "', defaulting to Melee\n";
1456 }
1457 }
1458
1460 return true;
1461}
Data-driven behavior tree system for AI decision making.
Core ECS component definitions.
RenderLayer
Render layer enumeration for Z-ordering.
@ Investigate
ComponentTypeID GetComponentTypeID_Static()
Definition ECS_Entity.h:56
std::uint64_t EntityID
Definition ECS_Entity.h:21
const EntityID INVALID_ENTITY_ID
Definition ECS_Entity.h:23
EntityType
Definition GameObject.h:22
static EntityType StringToEntityType(const std::string &typeStr)
void RegisterComponentFactory_Internal(const char *componentName, std::function< bool(EntityID, const ComponentDefinition &)> factory)
World and ECS Manager for Olympe Engine.
uint32_t GetTreeIdFromPath(const std::string &treePath) const
const BehaviorTreeAsset * GetTree(uint32_t treeId) const
static BehaviorTreeManager & Get()
static DataManager & Get()
Definition DataManager.h:87
Sprite * GetSprite(const std::string &id, const std::string &path, ResourceCategory category=ResourceCategory::GameEntity)
std::vector< ResolvedComponentInstance > Resolve(const PrefabBlueprint &prefab, const LevelInstanceParameters &instanceParams)
bool InstantiatePosition(EntityID entity, const ComponentDefinition &def)
bool InstantiateAIBehavior(EntityID entity, const ComponentDefinition &def)
void RegisterComponentFactory(const std::string &componentName, std::function< bool(EntityID, const ComponentDefinition &)> factory)
Register a component factory (called by auto-registration system)
bool InstantiateComponent(EntityID entity, const ComponentDefinition &componentDef)
Instantiate a single component on an entity.
bool InstantiateAttackIntent(EntityID entity, const ComponentDefinition &def)
bool InstantiateAudioSource(EntityID entity, const ComponentDefinition &def)
bool InstantiateCameraEffects(EntityID entity, const ComponentDefinition &def)
std::unique_ptr< PrefabScanner > m_scanner
std::map< std::string, std::function< bool(EntityID, const ComponentDefinition &)> > m_componentFactories
bool InstantiateCameraBounds(EntityID entity, const ComponentDefinition &def)
bool IsComponentRegistered(const std::string &componentName) const
Check if a component is registered.
bool InstantiatePhysicsBody(EntityID entity, const ComponentDefinition &def)
bool InstantiateCamera(EntityID entity, const ComponentDefinition &def)
bool InstantiatePlayerController(EntityID entity, const ComponentDefinition &def)
std::string NormalizeType(const std::string &type) const
Normalize a type string to canonical form.
bool InstantiateAIBlackboard(EntityID entity, const ComponentDefinition &def)
PrefabRegistry m_prefabRegistry
bool AreTypesEquivalent(const std::string &type1, const std::string &type2) const
Check if two types are equivalent.
bool InstantiateController(EntityID entity, const ComponentDefinition &def)
bool GetCanonicalInfo(const std::string &type, std::string &outCanonical, std::string &outPrefabFile) const
Get canonical type info for debugging.
void SetPrefabRegistry(const PrefabRegistry &registry)
Set the prefab registry cache.
bool IsTypeRegistered(const std::string &type) const
Check if a type is registered.
bool InstantiateBoundingBox(EntityID entity, const ComponentDefinition &def)
EntityID CreateEntityWithOverrides(const PrefabBlueprint &blueprint, const LevelInstanceParameters &instanceParams, bool autoAssignLayer=true)
Create entity from blueprint with level instance parameter overrides.
bool InstantiateVisualSprite(EntityID entity, const ComponentDefinition &def)
bool InstantiateVisualAnimation(EntityID entity, const ComponentDefinition &def)
bool InstantiateMoveIntent(EntityID entity, const ComponentDefinition &def)
std::vector< std::string > GetRegisteredComponents() const
Get list of all registered components (for debugging)
bool InstantiatePlayerBinding(EntityID entity, const ComponentDefinition &def)
bool InstantiateBehaviorTreeRuntime(EntityID entity, const ComponentDefinition &def)
EntityID CreateEntityFromBlueprint(const PrefabBlueprint &blueprint, bool autoAssignLayer=true)
Create entity from a parsed blueprint.
bool InstantiateCollisionZone(EntityID entity, const ComponentDefinition &def)
std::map< std::string, PrefabBuilder > m_prefabs
bool InstantiateVisualEditor(EntityID entity, const ComponentDefinition &def)
bool InstantiateFX(EntityID entity, const ComponentDefinition &def)
bool InstantiateAIState(EntityID entity, const ComponentDefinition &def)
static PrefabFactory & Get()
Get singleton instance.
bool InstantiateInputMapping(EntityID entity, const ComponentDefinition &def)
bool InstantiateNavigationAgent(EntityID entity, const ComponentDefinition &def)
bool InstantiateCameraInputBinding(EntityID entity, const ComponentDefinition &def)
bool InstantiateAISenses(EntityID entity, const ComponentDefinition &def)
bool InstantiateIdentity(EntityID entity, const ComponentDefinition &def)
EntityID CreateEntity(const std::string &prefabName)
Create an entity using legacy prefab system.
EntityID CreateEntityFromPrefabName(const std::string &prefabName)
Create entity from prefab name.
bool InstantiateAnimation(EntityID entity, const ComponentDefinition &def)
bool InstantiateHealth(EntityID entity, const ComponentDefinition &def)
bool InstantiateNPC(EntityID entity, const ComponentDefinition &def)
void PreloadAllPrefabs(const std::string &prefabDirectory="Blueprints/EntityPrefab")
Preload all prefabs from directory.
bool InstantiateTriggerZone(EntityID entity, const ComponentDefinition &def)
bool InstantiateMovement(EntityID entity, const ComponentDefinition &def)
bool InstantiateInventory(EntityID entity, const ComponentDefinition &def)
bool InstantiateCameraTarget(EntityID entity, const ComponentDefinition &def)
const PrefabBlueprint * Find(const std::string &name) const
std::vector< std::string > GetAllPrefabNames() const
int GetCount() const
Core ECS manager and world coordinator.
Definition World.h:210
static World & Get()
Get singleton instance (short form)
Definition World.h:232
T & AddComponent(EntityID entity, Args &&... args)
Definition World.h:393
bool HasComponent(EntityID entity) const
Definition World.h:451
RenderLayer GetDefaultLayerForType(EntityType type) const
Get the default render layer for an entity type Automatically assigns appropriate layer based on enti...
Definition World.h:473
T & GetComponent(EntityID entity)
Definition World.h:438
EntityID CreateEntity()
Definition World.cpp:225
void SetEntityLayer(EntityID entity, RenderLayer layer)
Set entity render layer (updates position.z)
Definition World.cpp:292
Header file for PrefabFactory class, responsible for creating game object prefabs.
std::string behaviorType
std::string animationID
std::string soundEffectID
Bounding box component for collision detection.
SDL_FRect boundingBox
Collision rectangle.
std::string effectType
Identity component for entity identification.
std::string name
Entity name identifier.
std::string npcType
Position component for spatial location.
Vector position
2D/3D position vector
std::vector< ComponentDefinition > components
ECS component for animated sprites.
#define SYSTEM_LOG