1 /**
2  * Copyright:       Copyright (C) 2018 Gabriel Gheorghe, All Rights Reserved
3  * Authors:         $(Gabriel Gheorghe)
4  * License:         $(LINK2 https://www.gnu.org/licenses/gpl-3.0.txt, GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007)
5  * Source:          $(LINK2 https://github.com/GabyForceQ/LibertyEngine/blob/master/source/liberty/scene/entity.d)
6  * Documentation:
7  * Coverage:
8 **/
9 module liberty.scene.entity;
10 
11 import liberty.camera;
12 import liberty.core.engine;
13 import liberty.framework.gui.vertex;
14 import liberty.framework.primitive.bsp;
15 import liberty.framework.primitive.vertex;
16 import liberty.framework.terrain.vertex;
17 import liberty.logger;
18 import liberty.math.transform;
19 import liberty.model.impl;
20 import liberty.scene.component;
21 import liberty.scene.constants;
22 import liberty.scene.impl;
23 import liberty.scene.services;
24 
25 /// Represents an entity in the scene tree.
26 /// It implements $(D IStartable) and $(D IUpdateable) service.
27 abstract class Entity : IStartable, IUpdateable {
28   private {
29     // It is used in spawnOnce methods
30     Entity[string] uniqueMap;
31     ///
32     IComponent[string] componentMap;
33   }
34 
35   protected {
36     ///
37     Transform transform;
38   }
39 
40   ///
41   string id;
42   ///
43   Scene scene;
44   ///
45   Visibility visibility;
46   ///
47   Model model;
48 
49   ///
50   typeof(this) addComponent(T : IComponent)(T component) {
51     import std.traits : EnumMembers;
52     
53     static foreach (e; EnumMembers!ComponentType)
54       static if (mixin("is(T == " ~ e ~ ")"))
55         componentMap[e] = component;
56 
57     return this;
58   }
59 
60   ///
61   typeof(this) removeComponent(ComponentType type) {
62     final switch (type) with (ComponentType) {
63       case Transform:
64         Logger.warning("Cannot remove transform component ever.", typeof(this).stringof);
65     }
66 
67     // For future components:
68     //componentMap.remove(id);
69     
70     return this;
71   }
72 
73   ///
74   T component(T : IComponent)() {
75     import std.traits : EnumMembers;
76 
77     static foreach (e; EnumMembers!ComponentType)
78       static if (mixin("is(T == " ~ e ~ ")"))
79         mixin("return cast(" ~ e ~ ")componentMap[e];");
80   }
81   
82   /// Construct a scene entity using an id and its parent.
83   this(string id) {
84     scene = CoreEngine.scene;
85     
86     // Check if given id is unique
87     if (id in scene.entityMap)
88       Logger.error(
89         "You already have a scene entity with ID: \"" ~ id ~ "\" in the current scene!",
90         typeof(this).stringof
91       );
92 
93     // Set transformation
94     transform = new Transform(this);
95     addComponent(transform);
96 
97     // Now save this in the scene entity map
98     scene.entityMap[id] = this;
99 
100     // Set model id
101     this.id = id;
102   }
103 
104   /// Called after all scene entitys instantiation.
105   /// It is optional.
106   void start() {}
107 
108   /// Called every frame to update the current state of the scene entity.
109   /// It is optional.
110   void update() {}
111 }