1 #pragma once
2 
3 //********************************************************************************************
4 //*
5 //*    This file is part of Egoboo.
6 //*
7 //*    Egoboo is free software: you can redistribute it and/or modify it
8 //*    under the terms of the GNU General Public License as published by
9 //*    the Free Software Foundation, either version 3 of the License, or
10 //*    (at your option) any later version.
11 //*
12 //*    Egoboo is distributed in the hope that it will be useful, but
13 //*    WITHOUT ANY WARRANTY; without even the implied warranty of
14 //*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 //*    General Public License for more details.
16 //*
17 //*    You should have received a copy of the GNU General Public License
18 //*    along with Egoboo.  If not, see <http://www.gnu.org/licenses/>.
19 //*
20 //********************************************************************************************
21 
22 /// @file egoboo_object.h
23 /// @details Definitions of data that all Egoboo objects should "inherit"
24 
25 #include "egoboo_typedef.h"
26 #include "egoboo_state_machine.h"
27 
28 //--------------------------------------------------------------------------------------------
29 //--------------------------------------------------------------------------------------------
30 // some basic data that all Egoboo objects should have
31 
32 /// The possible states of an obj_data_t object. The object is essentially
33 /// a state machine in the same way that the "egoboo process" is, so they use analagous
34 /// states
35 enum e_ego_object_state
36 {
37     ego_object_invalid        = ego_state_invalid,
38     ego_object_constructing   = ego_state_begin,     ///< The object has been allocated and had it's critical variables filled with safe values
39     ego_object_initializing   = ego_state_entering,  ///< The object is being initialized/re-initialized
40     ego_object_active         = ego_state_running,   ///< The object is fully activated
41     ego_object_deinitializing = ego_state_leaving,   ///< The object is being de-initialized
42     ego_object_destructing    = ego_state_finish,    ///< The object is being destructed
43 
44     // the states that are specific to objects
45     ego_object_waiting,                         ///< The object has been fully destructed and is awaiting final "deletion"
46     ego_object_terminated                       ///< The object is fully "deleted" and should now be on the free-store
47 };
48 typedef enum e_ego_object_state ego_object_state_t;
49 
50 //--------------------------------------------------------------------------------------------
51 
52 /// The data that is "inherited" by every Egoboo object.
53 struct s_ego_object_base
54 {
55     // basic object definitions
56     STRING             _name;     ///< what is its "_name"
57     size_t             index;     ///< what is the index position in the object list?
58     ego_object_state_t state;     ///< what state is it in?
59     Uint32             guid;      ///< a globally unique identifier
60 
61     // "process" control control
62     bool_t             allocated;   ///< Does it exist?
63     bool_t             on;          ///< Can it be accessed?
64     bool_t             turn_me_on;  ///< Has someone requested that the object be turned on?
65     bool_t             kill_me;     ///< Has someone requested that the object be destroyed?
66     bool_t             spawning;    ///< is the object in the midst of being created?
67 
68     bool_t             in_free_list; ///< the object is currently in the free list
69     bool_t             in_used_list; ///< the object is currently in the used list
70 
71     // things related to the updating of objects
72     size_t         update_count;  ///< How many updates have been made to this object?
73     size_t         frame_count;   ///< How many frames have been rendered?
74 
75     unsigned       update_guid;   ///< a value that lets you know if an object bookmark is in synch with the object list
76 };
77 
78 typedef struct s_ego_object_base obj_data_t;
79 
80 obj_data_t * ego_object_ctor( obj_data_t * pbase );
81 obj_data_t * ego_object_dtor( obj_data_t * pbase );
82 
83 //--------------------------------------------------------------------------------------------
84 //--------------------------------------------------------------------------------------------
85 
86 /// Mark a obj_data_t object as being allocated
87 #define POBJ_ALLOCATE( PDATA, INDEX ) \
88     if( NULL != PDATA ) \
89     { \
90         (PDATA)->obj_base.allocated  = btrue;  \
91         (PDATA)->obj_base.on         = bfalse; \
92         (PDATA)->obj_base.turn_me_on = bfalse; \
93         (PDATA)->obj_base.kill_me    = bfalse; \
94         (PDATA)->obj_base.spawning   = bfalse; \
95         (PDATA)->obj_base.index      = INDEX;  \
96         (PDATA)->obj_base.state      = ego_object_constructing; \
97         (PDATA)->obj_base.guid       = ego_object_guid++; \
98     }
99 
100 /// Turn on an obj_data_t object
101 #define POBJ_ACTIVATE( PDATA, NAME ) \
102     if( NULL != PDATA && (PDATA)->obj_base.allocated && !(PDATA)->obj_base.kill_me && ego_object_invalid != (PDATA)->obj_base.state ) \
103     { \
104         strncpy( (PDATA)->obj_base._name, NAME, SDL_arraysize((PDATA)->obj_base._name) ); \
105         (PDATA)->obj_base.state  = ego_object_active; \
106     }
107 
108 /// Begin turning off an obj_data_t object
109 #define POBJ_REQUEST_TERMINATE( PDATA ) \
110     if( NULL != PDATA && (PDATA)->obj_base.allocated && ego_object_invalid != (PDATA)->obj_base.state ) \
111     { \
112         if( ego_object_terminated != (PDATA)->obj_base.state ) \
113         { \
114             (PDATA)->obj_base.kill_me = btrue; \
115         } \
116         (PDATA)->obj_base.on = bfalse; \
117     }
118 
119 /// Completely turn off an obj_data_t object and mark it as no longer allocated
120 #define POBJ_TERMINATE( PDATA ) \
121     if( NULL != PDATA && (PDATA)->obj_base.allocated ) \
122     { \
123         (PDATA)->obj_base.allocated = bfalse; \
124         (PDATA)->obj_base.on        = bfalse; \
125         (PDATA)->obj_base.state     = ego_object_terminated; \
126     }
127 
128 #define POBJ_BEGIN_SPAWN( PDATA ) \
129     if( NULL != PDATA && (PDATA)->obj_base.allocated ) \
130     {\
131         if( !(PDATA)->obj_base.spawning )\
132         {\
133             (PDATA)->obj_base.spawning = btrue;\
134             ego_object_spawn_depth++;\
135         }\
136     }\
137 
138 #define POBJ_END_SPAWN( PDATA ) \
139     if( NULL != PDATA && (PDATA)->obj_base.allocated ) \
140     {\
141         if( (PDATA)->obj_base.spawning )\
142         {\
143             (PDATA)->obj_base.spawning = bfalse;\
144             ego_object_spawn_depth--;\
145         }\
146     }\
147 
148 /// Is the object flagged as requesting termination?
149 #define FLAG_ALLOCATED_PBASE( PBASE ) ( ( (PBASE)->allocated ) && (ego_object_invalid != (PBASE)->state) )
150 /// Is the object allocated?
151 #define ALLOCATED_PBASE( PBASE )       FLAG_ALLOCATED_PBASE(PBASE)
152 
153 /// Is the object flagged as requesting termination?
154 #define FLAG_ON_PBASE( PBASE )  ( (PBASE)->on )
155 /// Is the object on?
156 #define ON_PBASE( PBASE )       ( FLAG_ON_PBASE(PBASE) && (ego_object_invalid != (PBASE)->state) )
157 
158 /// Is the object flagged as kill_me?
159 #define FLAG_REQ_TERMINATION_PBASE( PBASE ) ( (PBASE)->kill_me )
160 /// Is the object kill_me?
161 #define REQ_TERMINATION_PBASE( PBASE )      ( FLAG_REQ_TERMINATION_PBASE(PBASE) && (ego_object_invalid != (PBASE)->state)  )
162 
163 /// Has the object been created yet?
164 #define STATE_CONSTRUCTING_PBASE( PBASE ) ( ego_object_constructing == (PBASE)->state )
165 /// Has the object been created yet?
166 #define CONSTRUCTING_PBASE( PBASE )       ( ALLOCATED_PBASE( PBASE ) && STATE_CONSTRUCTING_PBASE(PBASE) )
167 
168 /// Is the object in the initializing state?
169 #define STATE_INITIALIZING_PBASE( PBASE ) ( ego_object_initializing == (PBASE)->state )
170 /// Is the object being initialized right now?
171 #define INITIALIZING_PBASE( PBASE )       ( ALLOCATED_PBASE( PBASE ) && STATE_INITIALIZING_PBASE(PBASE) )
172 
173 /// Is the object in the active state?
174 #define STATE_ACTIVE_PBASE( PBASE ) ( ego_object_active == (PBASE)->state )
175 /// Is the object active?
176 #define ACTIVE_PBASE( PBASE )       ( ALLOCATED_PBASE( PBASE ) && STATE_ACTIVE_PBASE(PBASE) )
177 
178 /// Is the object in the deinitializing state?
179 #define STATE_DEINITIALIZING_PBASE( PBASE ) ( ego_object_deinitializing == (PBASE)->state )
180 /// Is the object being deinitialized right now?
181 #define DEINITIALIZING_PBASE( PBASE )       ( ALLOCATED_PBASE( PBASE ) && STATE_DEINITIALIZING_PBASE(PBASE) )
182 
183 /// Is the object in the destructing state?
184 #define STATE_DESTRUCTING_PBASE( PBASE ) ( ego_object_destructing == (PBASE)->state )
185 /// Is the object being deinitialized right now?
186 #define DESTRUCTING_PBASE( PBASE )       ( ALLOCATED_PBASE( PBASE ) && STATE_DESTRUCTING_PBASE(PBASE) )
187 
188 /// Is the object "waiting to die" state?
189 #define STATE_WAITING_PBASE( PBASE ) ( ego_object_waiting == (PBASE)->state )
190 /// Is the object "waiting to die"?
191 #define WAITING_PBASE( PBASE )       ( ALLOCATED_PBASE( PBASE ) && STATE_WAITING_PBASE(PBASE) )
192 
193 /// Has the object in the terminated state?
194 #define STATE_TERMINATED_PBASE( PBASE ) ( ego_object_terminated == (PBASE)->state )
195 /// Has the object been marked as terminated?
196 #define TERMINATED_PBASE( PBASE )       STATE_TERMINATED_PBASE(PBASE)
197 
198 /// Grab a pointer to the obj_data_t of an object that "inherits" this data
199 #define POBJ_GET_PBASE( POBJ )   ( &((POBJ)->obj_base) )
200 
201 /// Grab the index value of object that "inherits" from obj_data_t
202 #define GET_INDEX_POBJ( POBJ, FAIL_VALUE )  ( !ALLOCATED_PBASE( POBJ_GET_PBASE( POBJ ) ) ? FAIL_VALUE : (POBJ)->obj_base.index )
203 #define GET_REF_POBJ( POBJ, FAIL_VALUE )    ((REF_T)GET_INDEX_POBJ( POBJ, FAIL_VALUE ))
204 
205 /// Grab the state of object that "inherits" from obj_data_t
206 #define GET_STATE_POBJ( POBJ )  ( !ALLOCATED_PBASE( POBJ_GET_PBASE( POBJ ) ) ? ego_object_invalid : (POBJ)->obj_base.index )
207 
208 //--------------------------------------------------------------------------------------------
209 //--------------------------------------------------------------------------------------------
210 
211 /// A variable to hold the object guid counter
212 extern Uint32 ego_object_guid;
213 
214 extern Uint32 ego_object_spawn_depth;
215 
216 //--------------------------------------------------------------------------------------------
217 //--------------------------------------------------------------------------------------------
218 #define egoboo_object_h