-
-
Notifications
You must be signed in to change notification settings - Fork 183
/
Copy pathComponent.h
289 lines (232 loc) · 8.52 KB
/
Component.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
/*
* Copyright (c) scott.cgi All Rights Reserved.
*
* This source code belongs to project Mojoc, which is a pure C Game Engine hosted on GitHub.
* The Mojoc Game Engine is licensed under the MIT License, and will continue to be iterated with coding passion.
*
* License : https://github.com/scottcgi/Mojoc/blob/master/LICENSE
* GitHub : https://github.com/scottcgi/Mojoc
* CodeStyle: https://github.com/scottcgi/Mojoc/blob/master/Docs/CodeStyle.md
*
* Since : 2015-8-19
* Update : 2019-1-26
* Author : scott.cgi
*/
#ifndef COMPONENT_H
#define COMPONENT_H
#include "Engine/Toolkit/Utils/ArrayIntMap.h"
#include "Engine/Toolkit/Utils/ArrayIntSet.h"
#include "Engine/Toolkit/HeaderUtils/UserData.h"
typedef struct Component Component;
typedef struct ComponentState ComponentState;
/**
* Component has a State-Machine, message subscription list, and component child list.
* State-Machine make component can switch self state.
* message subscription make component can send message to subscriber.
* components and sub components form a tree structure that make message can delivery to any child.
*
* also component can sort children by order, but not draw or render anything.
* The function of draw or render need to sub component implementation,
* such as SpriteComponent that is component with sprite,
* and then the component can draw sprite,
* the sprite has component's State-Machine, message subscription so on.
*/
struct Component
{
UserData userData[1];
/**
* If isActive false Component will not change state, update state, handle and send message.
*/
bool isActive;
/**
* Order in parent children list when add in auto setting.
* if changed it then ReorderAllChildren will resort Component order in parent list.
*/
int order;
/**
* When append child the order increased by deltaOrder, default 100.
*/
int deltaOrder;
/**
* Component's parent in a tree structure.
*/
Component* parent;
/**
* Current active state, default is defaultState.
*/
ComponentState* curState;
/**
* Previous active state, default is defaultState.
*/
ComponentState* preState;
/**
* Default state when Component created with stateID ComponentState_Default.
*/
ComponentState* defaultState;
/**
* Children mapped by Component order.
*/
ArrayIntMap(order, Component*) childMap [1];
/**
* Component notification observers.
*/
ArrayIntSet(Component*) observerSet[1];
/**
* All ComponentStates mapped by ComponentState's id.
*/
ArrayIntMap(stateID, ComponentState*) stateMap [1];
};
/**
* ComponentState stateID.
*/
enum
{
/**
* ComponentState default stateID, any other stateID must be different.
*/
ComponentState_Default = 0
};
/**
* ComponentState subject.
*
* Component's ComponentState may receive this type of subject message,
* then OnMessage called for handle.
*/
enum
{
/**
* When ComponentState enter.
*
* sender : AComponent
* extraData: NULL
*/
ComponentMsg_OnEnter,
/**
* When ComponentState exit.
*
* sender : AComponent
* extraData: NULL
*/
ComponentMsg_OnExit,
};
/**
* Component's ComponentState for handle different logic in different states.
*/
struct ComponentState
{
UserData userData[1];
/**
* Key in Component's stateMap
*/
int id;
/**
* Active ComponentState called every frame.
*/
void (*Update) (Component* component, float deltaSeconds);
/**
* After Component's children updated called every frame.
*/
void (*UpdateAfter) (Component* component, float deltaSeconds);
/**
* When message received called.
* if return true means consumed event then will stop event passing.
*/
bool (*OnMessage) (Component* component, void* sender, int subject, void* extraData);
};
typedef void (*ComponentStateUpdate) (Component* component, float deltaSeconds);
typedef bool (*ComponentStateOnMessage)(Component* component, void* sender, int subject, void* extraData);
/**
* Manage and control Component.
*/
struct AComponent
{
/**
* Create new Component that malloc memory and need to free it manually.
*/
Component* (*Create) (void);
/**
* Init Component that memory has already malloc.
*/
void (*Init) (Component* outComponent);
/**
* Free members memory and reset some property values.
*/
void (*Release) (Component* component);
//----------------------------------------------------------------------------------------------------------------------
/**
* Add child into parent's children list by order.
*/
void (*AddChild) (Component* parent, Component* child, int order);
/**
* Append child and auto set child order by deltaOrder.
*/
void (*AppendChild) (Component* parent, Component* child);
/**
* Remove child from parent's children list and reindex other children.
*/
void (*RemoveChild) (Component* parent, Component* child);
/**
* Remove all children from parent.
*/
void (*RemoveAllChildren) (Component* parent);
/**
* Reorder all children by child's order.
* we should apply this method after Component order changed. (may after all orders changes have been completed)
*/
void (*ReorderAllChildren) (Component* parent);
//----------------------------------------------------------------------------------------------------------------------
/**
* Add observer to sender, will receive notification by sender.
*/
void (*AddObserver) (Component* sender, Component* observer);
/**
* Remove observer from sender.
*/
void (*RemoveObserver) (Component* sender, Component* observer);
/**
* Send message to component self and children (depth-first traversal),
* and will call self and children's ComponentState OnMessage method,
* and the component order bigger the response first.
*
* if any OnMessage return true means consumed event then will stop event passing.
* if in OnMessage removed parent child will cause error.
* if component isActive false will do nothing.
*/
bool (*SendMessage) (Component* component, void* sender, int subject, void* extraData);
/**
* Notify sender all observers,
* and will call observers ComponentState OnMessage method.
*
* if sender isActive false will do nothing.
* if observers isActive false will not call OnMessage.
* if in observers OnMessage removed sender observer will cause error.
*/
void (*Notify) (Component* sender, int subject, void* extraData);
//----------------------------------------------------------------------------------------------------------------------
/**
* Change Component current active State.
* if component isActive false will do nothing.
*/
void (*SetState) (Component* component, int stateID);
/**
* Create ComponentState with stateID, and add into Component.
* the add ComponentState free by Component's Release.
*/
ComponentState* (*AddState) (
Component* component,
int stateID,
ComponentStateOnMessage OnMessage,
ComponentStateUpdate Update
);
//----------------------------------------------------------------------------------------------------------------------
/**
* Set Component and all children active state.
*/
void (*SetActive) (Component* component, bool isActive);
/**
* Update Component self and children's state that will call ComponentState update method.
*/
void (*Update) (Component* component, float deltaSeconds);
};
extern struct AComponent AComponent[1];
#endif