FS2_Open
Open source remastering of the Freespace 2 engine
parseobjectdock.cpp
Go to the documentation of this file.
1 /*
2  * Created by Ian "Goober5000" Warfield for the FreeSpace2 Source Code Project.
3  * You may not sell or otherwise commercially exploit the source or things you
4  * create based on the source.
5  */
6 
7 
8 
9 #include "globalincs/pstypes.h"
10 #include "math/bitarray.h"
11 #include "mission/missionparse.h"
12 #include "object/parseobjectdock.h"
13 
14 
15 
16 
17 // helper prototypes
18 
19 void dock_evaluate_tree(p_object *objp, p_dock_function_info *infop, void (*function)(p_object *, p_dock_function_info *), ubyte *visited_bitstring);
20 void dock_dock_docked_children_tree(p_object *objp, p_object *parent_objp);
21 
22 
23 // management prototypes
24 
25 void dock_add_instance(p_object *objp, char *dockpoint, p_object *other_objp);
27 p_dock_instance *dock_find_instance(p_object *objp, char *dockpoint);
28 
29 
31 {
32  return (objp->dock_list != NULL);
33 }
34 
36 {
37  // are we docked?
38  if (!object_is_docked(objp))
39  return NULL;
40 
41  return objp->dock_list->docked_objp;
42 }
43 
45 {
46  // we must be docked
47  if (!object_is_docked(objp))
48  return false;
49 
50  // our dock list must contain only one object
51  if (objp->dock_list->next != NULL)
52  return false;
53 
54  // the other guy's dock list must contain only one object
55  if (dock_get_first_docked_object(objp)->dock_list->next != NULL)
56  return false;
57 
58  // debug check to make sure that we're docked to each other
59  Assert(objp == dock_get_first_docked_object(objp)->dock_list->docked_objp);
60 
61  // success
62  return true;
63 }
64 
66 {
67  return (dock_find_instance(objp, other_objp) != NULL);
68 }
69 
71 {
72  p_dock_instance *result = dock_find_instance(objp, dockpoint);
73 
74  if (result == NULL)
75  return NULL;
76  else
77  return result->docked_objp;
78 }
79 
81 {
82  p_dock_instance *result = dock_find_instance(objp, other_objp);
83 
84  if (result == NULL)
85  return NULL;
86  else
87  return result->dockpoint_used;
88 }
89 
90 // functions to deal with all docked objects anywhere
91 // ---------------------------------------------------------------------------------------------------------------
92 
93 // universal two functions
94 // -----------------------
95 
96 // evaluate a certain function for all docked objects
98 {
99  Assert((objp != NULL) && (infop != NULL) && (function != NULL));
100 
101  // not docked?
102  if (!object_is_docked(objp))
103  {
104  // call the function for just the one object
105  function(objp, infop);
106  return;
107  }
108 
109  // we only have two objects docked
111  {
112  // call the function for the first object, and return if instructed
113  function(objp, infop);
114  if (infop->early_return_condition) return;
115 
116  // call the function for the second object, and return if instructed
117  function(objp->dock_list->docked_objp, infop);
118  if (infop->early_return_condition) return;
119  }
120 
121  // NOTE - never treat a group of parse objects as a hub... it cuts down on bugs, and it's
122  // not needed because it's not time-critical
123 
124  // we have multiple objects docked and we must treat them as a tree
125  else
126  {
127  // create a bit array to mark the objects we check
128  ubyte *visited_bitstring = (ubyte *) vm_malloc(calculate_num_bytes(Parse_objects.size()));
129 
130  // clear it
131  memset(visited_bitstring, 0, calculate_num_bytes(Parse_objects.size()));
132 
133  // start evaluating the tree
134  dock_evaluate_tree(objp, infop, function, visited_bitstring);
135 
136  // destroy the bit array
137  vm_free(visited_bitstring);
138  visited_bitstring = NULL;
139  }
140 }
141 
142 void dock_evaluate_tree(p_object *objp, p_dock_function_info *infop, void (*function)(p_object *, p_dock_function_info *), ubyte *visited_bitstring)
143 {
144  // make sure we haven't visited this object already
145  if (get_bit(visited_bitstring, POBJ_INDEX(objp)))
146  return;
147 
148  // mark as visited
149  set_bit(visited_bitstring, POBJ_INDEX(objp));
150 
151  // call the function for this object, and return if instructed
152  function(objp, infop);
153  if (infop->early_return_condition) return;
154 
155  // iterate through all docked objects
156  for (p_dock_instance *ptr = objp->dock_list; ptr != NULL; ptr = ptr->next)
157  {
158  // start another tree with the docked object as the root, and return if instructed
159  dock_evaluate_tree(ptr->docked_objp, infop, function, visited_bitstring);
160  if (infop->early_return_condition) return;
161  }
162 }
163 
164 // special-case functions
165 // ----------------------
166 
168 {
169  if (!object_is_docked(objp))
170  return;
171 
172  // has this object (by extension, this group of docked objects) been handled already?
173  if (objp->flags2 & P2_ALREADY_HANDLED)
174  return;
175 
176  Assert(objp->flags & P_SF_DOCK_LEADER);
177 
179 
180  // start a tree with that object as the parent... do NOT use the überfunction for this,
181  // because we must use a tree for the parent ancestry to work correctly
182 
183  // we don't need a bit array because P2_ALREADY_HANDLED takes care of it
184 
185  // start evaluating the tree, starting with the dock leader
186  dock_dock_docked_children_tree(objp, NULL);
187 }
188 
190 {
191  // has this object been handled already?
192  if (objp->flags2 & P2_ALREADY_HANDLED)
193  return;
194 
195  // mark as handled
196  objp->flags2 |= P2_ALREADY_HANDLED;
197 
198  // if parent_objp exists
199  if (parent_objp != NULL)
200  {
201  // dock this object to it
202  parse_dock_one_docked_object(objp, parent_objp);
203  }
204 
205  // iterate through all docked objects
206  for (p_dock_instance *ptr = objp->dock_list; ptr != NULL; ptr = ptr->next)
207  {
208  // start another tree with the docked object as the root and this object as the parent
209  dock_dock_docked_children_tree(ptr->docked_objp, objp);
210  }
211 }
212 // ---------------------------------------------------------------------------------------------------------------
213 // end of über code block ----------------------------------------------------------------------------------------
214 
215 // dock management functions -------------------------------------------------------------------------------------
216 void dock_dock_objects(p_object *objp1, char *dockpoint1, p_object *objp2, char *dockpoint2)
217 {
218 #ifndef NDEBUG
219  if ((dock_find_instance(objp1, objp2) != NULL) || (dock_find_instance(objp2, objp1) != NULL))
220  {
221  Error(LOCATION, "Trying to dock an object that's already docked!\n");
222  }
223 
224  if ((dock_find_instance(objp1, dockpoint1) != NULL) || (dock_find_instance(objp2, dockpoint2) != NULL))
225  {
226  Error(LOCATION, "Trying to dock to a dockpoint that's in use!\n");
227  }
228 #endif
229 
230  // put objects on each others' dock lists
231  dock_add_instance(objp1, dockpoint1, objp2);
232  dock_add_instance(objp2, dockpoint2, objp1);
233 }
234 
235 // dock list functions -------------------------------------------------------------------------------------------
236 void dock_add_instance(p_object *objp, char *dockpoint, p_object *other_objp)
237 {
238  p_dock_instance *item;
239 
240  // create item
241  item = (p_dock_instance *) vm_malloc(sizeof(p_dock_instance));
242  strcpy_s(item->dockpoint_used, dockpoint);
243  item->docked_objp = other_objp;
244 
245  // prepend item to existing list
246  item->next = objp->dock_list;
247  objp->dock_list = item;
248 }
249 
250 // just free the list without worrying about undocking anything
252 {
253  while (objp->dock_list != NULL)
254  {
255  p_dock_instance *ptr = objp->dock_list;
256  objp->dock_list = ptr->next;
257  vm_free(ptr);
258  }
259 }
260 
262 {
263  p_dock_instance *ptr = objp->dock_list;
264 
265  // iterate until item found
266  while (ptr != NULL)
267  {
268  // if found, return it
269  if (ptr->docked_objp == other_objp)
270  return ptr;
271 
272  // iterate
273  ptr = ptr->next;
274  }
275 
276  // not found
277  return NULL;
278 }
279 
281 {
282  p_dock_instance *ptr = objp->dock_list;
283 
284  // iterate until item found
285  while (ptr != NULL)
286  {
287  // if found, return it
288  if (!strcmp(ptr->dockpoint_used, dockpoint))
289  return ptr;
290 
291  // iterate
292  ptr = ptr->next;
293  }
294 
295  // not found
296  return NULL;
297 }
GLuint64EXT * result
Definition: Glext.h:10775
#define vm_free(ptr)
Definition: pstypes.h:548
void dock_evaluate_all_docked_objects(p_object *objp, p_dock_function_info *infop, void(*function)(p_object *, p_dock_function_info *))
void dock_dock_docked_objects(p_object *objp)
SCP_vector< p_object > Parse_objects
p_object * next
Definition: missionparse.h:347
Assert(pm!=NULL)
bool dock_check_find_direct_docked_object(p_object *objp, p_object *other_objp)
p_object * dock_get_first_docked_object(p_object *objp)
p_dock_instance * next
void dock_evaluate_tree(p_object *objp, p_dock_function_info *infop, void(*function)(p_object *, p_dock_function_info *), ubyte *visited_bitstring)
object * objp
Definition: lua.cpp:3105
void dock_add_instance(p_object *objp, char *dockpoint, p_object *other_objp)
#define calculate_num_bytes(num_bits)
Definition: bitarray.h:46
#define set_bit(array, bitnum)
Definition: bitarray.h:36
#define get_bit(array, bitnum)
Definition: bitarray.h:33
#define P_SF_DOCK_LEADER
Definition: missionparse.h:477
p_object * dock_find_object_at_dockpoint(p_object *objp, char *dockpoint)
void dock_dock_objects(p_object *objp1, char *dockpoint1, p_object *objp2, char *dockpoint2)
#define POBJ_INDEX(pobjp)
Definition: missionparse.h:523
p_object * docked_objp
bool object_is_docked(p_object *objp)
char * dock_find_dockpoint_used_by_object(p_object *objp, p_object *other_objp)
unsigned char ubyte
Definition: pstypes.h:62
void _cdecl void void _cdecl Error(const char *filename, int line, SCP_FORMAT_STRING const char *format,...) SCP_FORMAT_STRING_ARGS(3
#define vm_malloc(size)
Definition: pstypes.h:547
void dock_free_dock_list(p_object *objp)
void dock_dock_docked_children_tree(p_object *objp, p_object *parent_objp)
#define LOCATION
Definition: pstypes.h:245
void parse_dock_one_docked_object(p_object *pobjp, p_object *parent_pobjp)
char dockpoint_used[NAME_LENGTH]
p_dock_instance * dock_find_instance(p_object *objp, p_object *other_objp)
bool dock_check_docked_one_on_one(p_object *objp)
p_dock_instance * dock_list
Definition: missionparse.h:395
#define P2_ALREADY_HANDLED
Definition: missionparse.h:518
#define strcpy_s(...)
Definition: safe_strings.h:67