World Object.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. namespace EE{
  4. namespace Game{
  5. /******************************************************************************/
  6. Bool WorldManager::areaInsertObject(Area &area, Obj &obj, AREA_STATE obj_state)
  7. {
  8. // test the state of target area
  9. if(!area.loaded()) // if target area hasn't yet been loaded
  10. {
  11. switch(_mode)
  12. {
  13. case WORLD_STREAM:
  14. case WORLD_MANUAL:
  15. {
  16. // in stream and manual modes, we flush the object to a temporary file
  17. // don't delete object, deletion will be handled outside
  18. if(obj.canBeSaved())area.saveObj(obj);
  19. }return false; // return false stating that the object should be deleted
  20. case WORLD_FULL:
  21. {
  22. if(!obj.canBeSaved())return false; // WORLD_FULL does not imply any limits to the area dimensions, so just for safety, check if the object wants to be put in that area ('canBeSaved' can be used to skip objects moved too far away)
  23. File f;
  24. areaUpdateState (area, f); // for WORLD_FULL an Area can be not yet loaded, so we need to update its state (to loaded)
  25. areaSetLoadedRect( ); // after adding new area we need to update loaded rectangles
  26. }break;
  27. }
  28. }
  29. obj.putToArea(area);
  30. if(obj_state!=area.state())
  31. {
  32. if(area.state()==AREA_ACTIVE)obj. enable();
  33. else obj.disable();
  34. }
  35. return true;
  36. }
  37. /******************************************************************************/
  38. Bool WorldManager::loadObj(Area &area, Bool active, Area::Data::AreaObj &area_obj, Bool _const)
  39. {
  40. Int obj_type=ObjType.find(area_obj.type()); // OBJ_TYPE
  41. if(ObjMap<Obj> *obj_map =objMap(obj_type))
  42. if(Obj *obj =obj_map->_map(area_obj.id))
  43. {
  44. obj->init (_const, obj_type, &area_obj.id);
  45. obj->create (area_obj);
  46. obj->memoryAddressChanged();
  47. obj->putToArea (area);
  48. if(active)obj-> enable();
  49. else obj->disable();
  50. _obj_newly_added.add(obj);
  51. return true;
  52. }
  53. return false;
  54. }
  55. Bool WorldManager::loadObj(Area &area, Bool active, Int obj_type, File &f)
  56. {
  57. if(ObjMap<Obj> *obj_map=objMap(obj_type))
  58. if(Obj *obj =obj_map->_map(UIDZero)) // we don't know yet the ID of the object, because it's stored in 'obj_save_data', so create with 'UIDZero' and later replace it
  59. {
  60. obj->init(false, obj_type);
  61. if(obj->load(f))
  62. {
  63. obj_map->_map.replaceKey(UIDZero, obj->id()); // replace with proper key
  64. obj->memoryAddressChanged();
  65. obj->putToArea (area);
  66. if(active)obj-> enable();
  67. else obj->disable();
  68. _obj_newly_added.add(obj);
  69. return true;
  70. }else
  71. {
  72. obj_map->removeObj(obj);
  73. }
  74. }
  75. return false;
  76. }
  77. /******************************************************************************/
  78. Obj* WorldManager::objCreateNear(Object &object, C Matrix &matrix, C UID *obj_id)
  79. {
  80. Int obj_type=ObjType.find(object.type()); // OBJ_TYPE
  81. if(ObjMap<Obj> *obj_map=objMap(obj_type))
  82. {
  83. UID oid; if(obj_id)oid=*obj_id;else oid.randomize();
  84. VecI2 xz=worldToArea(matrix.pos);
  85. if(Area *area=_grid.get(xz).data())if(area->loaded())
  86. if(Obj *obj =obj_map->_map(oid))
  87. {
  88. Object child; child.base(&object); child.matrix=matrix;
  89. obj->init (false, obj_type, &oid);
  90. obj->create (child);
  91. obj->memoryAddressChanged();
  92. obj->putToArea (*area);
  93. if(area->state()==AREA_ACTIVE)obj->enable ();
  94. else obj->disable();
  95. return obj;
  96. }
  97. }
  98. return null;
  99. }
  100. Bool WorldManager::objCreate(Object &object, C Matrix &matrix, C UID *obj_id)
  101. {
  102. Int obj_type=ObjType.find(object.type()); // OBJ_TYPE
  103. if(ObjMap<Obj> *obj_map=objMap(obj_type))
  104. {
  105. UID oid; if(obj_id)oid=*obj_id;else oid.randomize();
  106. if(Obj *obj=obj_map->_map(oid))
  107. {
  108. Object child; child.base(&object); child.matrix=matrix;
  109. obj->init (false, obj_type, &oid);
  110. obj->create (child);
  111. obj->memoryAddressChanged();
  112. if(!obj->updateArea ())obj_map->removeObj(obj);
  113. return true;
  114. }
  115. }
  116. return false;
  117. }
  118. Bool WorldManager::objInject(Int obj_type, File &obj_save_data, C Vec *pos)
  119. {
  120. if(ObjMap<Obj> *obj_map=objMap(obj_type))
  121. if(Obj *obj=obj_map->_map(UIDZero)) // we don't know yet the ID of the object, because it's stored in 'obj_save_data', so create with 'UIDZero' and later replace it
  122. {
  123. obj->init(false, obj_type);
  124. if(obj->load(obj_save_data))
  125. {
  126. obj_map->_map.replaceKey(UIDZero, obj->id()); // replace with proper key
  127. obj->memoryAddressChanged();
  128. if(pos)obj->pos(*pos);
  129. if(!obj->updateArea())obj_map->removeObj(obj);else _obj_newly_added.add(obj);
  130. return true;
  131. }
  132. obj_map->removeObj(obj);
  133. }
  134. return false;
  135. }
  136. /******************************************************************************/
  137. Obj* WorldManager::moveWorldObjToStorage(Obj &world_obj, Memx<Obj> &storage)
  138. {
  139. if( world_obj._area) // if object belongs to an area
  140. if(ObjMap<Obj> *world_storage=world_obj.worldObjMap()) // if item is stored in world container
  141. if( world_storage->elmSize()==storage.elmSize()) // if elements stored in containers are of the same sizes
  142. {
  143. Obj &storage_obj=storage.New(); // create new object in the storage
  144. if(CType(world_obj)==CType(storage_obj)) // if objects are of same class
  145. {
  146. world_obj.willBeMovedFromWorldToStorage(); // callback
  147. world_obj.removeFromArea(); // remove from area
  148. Swap(&world_obj, &storage_obj, storage.elmSize()); // swap object data
  149. world_storage->removeObj(&world_obj); // remove from world container
  150. storage_obj.memoryAddressChanged(); // notify that memory address was changed
  151. storage_obj.wasMovedFromWorldToStorage(); // callback
  152. return &storage_obj;
  153. }else
  154. {
  155. storage.removeData(&storage_obj);
  156. }
  157. }
  158. return null;
  159. }
  160. Bool WorldManager::moveStorageObjToWorld(Obj &storage_obj, Memx<Obj> &storage, C Matrix *obj_matrix)
  161. {
  162. if(storage.contains(&storage_obj)) // if belongs to this storage
  163. if(ObjMap<Obj> *world_storage=objMap(objType(storage_obj))) // if world has storage for this object
  164. if( world_storage->elmSize()==storage.elmSize()) // if elements stored in containers are of the same sizes
  165. if(Obj *world_obj=world_storage->_map(storage_obj.id())) // if created object
  166. {
  167. if(CType(storage_obj)==CType(*world_obj)) // if objects are of same class
  168. {
  169. storage_obj.willBeMovedFromStorageToWorld(); // callback
  170. Swap(&storage_obj, world_obj, world_storage->elmSize()); // swap object data
  171. storage.removeData(&storage_obj); // remove from storage
  172. world_obj->memoryAddressChanged(); // notify that memory address was changed
  173. if(obj_matrix)world_obj->matrix(*obj_matrix); // set matrix
  174. world_obj->wasMovedFromStorageToWorld(); // callback
  175. if(!areaInsertObject(*_grid.get(worldToArea(world_obj->pos())).data(), *world_obj, AREA_UNLOADED)) // add to area
  176. {
  177. world_storage->removeObj(world_obj); // remove from world container if object was added to unloaded area
  178. }
  179. return true;
  180. }else
  181. {
  182. world_storage->removeObj(world_obj);
  183. }
  184. }
  185. return false;
  186. }
  187. Obj* WorldManager::MoveStorageObjToStorage(Obj &storage_obj, Memx<Obj> &src_storage, Memx<Obj> &dest_storage)
  188. {
  189. if(&src_storage ==&dest_storage)return &storage_obj; // same containers
  190. if( src_storage.elmSize()== dest_storage.elmSize()) // if elements stored in containers are of the same sizes
  191. if( src_storage.contains(&storage_obj)) // if belongs to this storage
  192. {
  193. Obj &dest_obj=dest_storage.New(); // create new object in world
  194. if(CType(storage_obj)==CType(dest_obj)) // if objects are of same class
  195. {
  196. Swap(&storage_obj, &dest_obj, dest_storage.elmSize()); // swap object data
  197. src_storage.removeData(&storage_obj); // remove from src storage
  198. dest_obj.memoryAddressChanged(); // notify that memory address was changed
  199. return &dest_obj;
  200. }else
  201. {
  202. dest_storage.removeData(&dest_obj);
  203. }
  204. }
  205. return null;
  206. }
  207. /******************************************************************************/
  208. struct ObjGetBall
  209. {
  210. Int obj_type;
  211. Vec ball_pos;
  212. Flt ball_r2 ; // squared radius for faster calculations
  213. MemPtr<Obj*> &objects ;
  214. ObjGetBall(MemPtr<Obj*> &objects, C Ball &ball, Int obj_type) : objects(objects), obj_type(obj_type) {ball_pos=ball.pos; ball_r2=Sqr(ball.r);}
  215. };
  216. static void ObjGetAddBall(Cell<Area> &cell, ObjGetBall &oq)
  217. {
  218. if(cell().loaded())
  219. {
  220. Int type=oq.obj_type;
  221. Memc<Obj*> &objs=cell()._objs;
  222. REPA(objs)
  223. {
  224. Obj &o=*objs[i];
  225. if(type<0 || o.type()==type)if(Dist2(o.pos(), oq.ball_pos)<=oq.ball_r2)oq.objects.add(&o);
  226. }
  227. }
  228. }
  229. struct ObjGetCapsule
  230. {
  231. Int obj_type;
  232. Edge edge ;
  233. Flt radius ;
  234. MemPtr<Obj*> &objects ;
  235. ObjGetCapsule(MemPtr<Obj*> &objects, C Capsule &capsule, Int obj_type) : objects(objects), obj_type(obj_type)
  236. {
  237. Vec up=(capsule.h*0.5f-capsule.r)*capsule.up;
  238. edge.p[0]= capsule.pos-up;
  239. edge.p[1]= capsule.pos+up;
  240. radius = capsule.r;
  241. }
  242. };
  243. static void ObjGetAddCapsule(Cell<Area> &cell, ObjGetCapsule &oq)
  244. {
  245. if(cell().loaded())
  246. {
  247. Int type=oq.obj_type;
  248. Memc<Obj*> &objs=cell()._objs;
  249. REPA(objs)
  250. {
  251. Obj &o=*objs[i];
  252. if(type<0 || o.type()==type)if(Dist(o.pos(), oq.edge)<=oq.radius)oq.objects.add(&o);
  253. }
  254. }
  255. }
  256. struct ObjGetBox
  257. {
  258. Int obj_type;
  259. Box box ;
  260. MemPtr<Obj*> &objects ;
  261. ObjGetBox(MemPtr<Obj*> &objects, C Box &box, Int obj_type) : objects(objects), box(box), obj_type(obj_type) {}
  262. };
  263. static void ObjGetAddBox(Cell<Area> &cell, ObjGetBox &oq)
  264. {
  265. if(cell().loaded())
  266. {
  267. Int type=oq.obj_type;
  268. Memc<Obj*> &objs=cell()._objs;
  269. REPA(objs)
  270. {
  271. Obj &o=*objs[i];
  272. if(type<0 || o.type()==type)if(Cuts(o.pos(), oq.box))oq.objects.add(&o);
  273. }
  274. }
  275. }
  276. struct ObjGetOBox
  277. {
  278. Int obj_type;
  279. OBox obox ;
  280. MemPtr<Obj*> &objects ;
  281. ObjGetOBox(MemPtr<Obj*> &objects, C OBox &obox, Int obj_type) : objects(objects), obox(obox), obj_type(obj_type) {}
  282. };
  283. static void ObjGetAddOBox(Cell<Area> &cell, ObjGetOBox &oq)
  284. {
  285. if(cell().loaded())
  286. {
  287. Int type=oq.obj_type;
  288. Memc<Obj*> &objs=cell()._objs;
  289. REPA(objs)
  290. {
  291. Obj &o=*objs[i];
  292. if(type<0 || o.type()==type)if(Cuts(o.pos(), oq.obox))oq.objects.add(&o);
  293. }
  294. }
  295. }
  296. WorldManager& WorldManager::objGetAdd(MemPtr<Obj*> objects, C Ball &ball, Int obj_type)
  297. {
  298. ObjGetBall oq(objects, ball, obj_type);
  299. _grid.func(worldToArea(Rect(ball.pos.x-ball.r, ball.pos.z-ball.r, ball.pos.x+ball.r, ball.pos.z+ball.r))&_area_loaded_rect, ObjGetAddBall, oq);
  300. return T;
  301. }
  302. WorldManager& WorldManager::objGetAdd(MemPtr<Obj*> objects, C Capsule &capsule, Int obj_type)
  303. {
  304. ObjGetCapsule oq(objects, capsule, obj_type);
  305. _grid.func(worldToArea(Rect().from(oq.edge.p[0].xz(), oq.edge.p[1].xz()).extend(capsule.r))&_area_loaded_rect, ObjGetAddCapsule, oq);
  306. return T;
  307. }
  308. WorldManager& WorldManager::objGetAdd(MemPtr<Obj*> objects, C Box &box, Int obj_type)
  309. {
  310. ObjGetBox oq(objects, box, obj_type);
  311. _grid.func(worldToArea(box)&_area_loaded_rect, ObjGetAddBox, oq);
  312. return T;
  313. }
  314. WorldManager& WorldManager::objGetAdd(MemPtr<Obj*> objects, C OBox &obox, Int obj_type)
  315. {
  316. ObjGetOBox oq(objects, obox, obj_type);
  317. _grid.func(worldToArea(obox)&_area_loaded_rect, ObjGetAddOBox, oq);
  318. return T;
  319. }
  320. /******************************************************************************/
  321. Obj* WorldManager::findObjById(C UID &obj_id, Int obj_type)
  322. {
  323. if(obj_id.valid())
  324. {
  325. if(obj_type<0) // search in all containers
  326. {
  327. REPA(_obj_container)if(ObjMap<Obj> *obj_map=_obj_container[i].map)if(Obj *obj=obj_map->find(obj_id))return obj;
  328. }else
  329. if(ObjMap<Obj> *obj_map=objMap(obj_type))
  330. {
  331. return obj_map->find(obj_id);
  332. }
  333. }
  334. return null;
  335. }
  336. /******************************************************************************/
  337. }}
  338. /******************************************************************************/