/src/lib/de/polygonal/motor/dynamics/contact/ContactFactory.hx

http://polygonal.googlecode.com/ · Haxe · 233 lines · 167 code · 31 blank · 35 comment · 19 complexity · 82669a12de59aba5cd58b276a821471d MD5 · raw file

  1. /*
  2. * _/ _/
  3. * _/_/_/ _/_/ _/ _/ _/ _/_/_/ _/_/ _/_/_/ _/_/_/ _/
  4. * _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/
  5. * _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/
  6. * _/_/_/ _/_/ _/ _/_/_/ _/_/_/ _/_/ _/ _/ _/_/_/ _/
  7. * _/ _/ _/
  8. * _/ _/_/ _/_/
  9. *
  10. * POLYGONAL - A HAXE LIBRARY FOR GAME DEVELOPERS
  11. * Copyright (c) 2009-2010 Michael Baczynski, http://www.polygonal.de
  12. *
  13. * Permission is hereby granted, free of charge, to any person obtaining
  14. * a copy of this software and associated documentation files (the
  15. * "Software"), to deal in the Software without restriction, including
  16. * without limitation the rights to use, copy, modify, merge, publish,
  17. * distribute, sublicense, and/or sell copies of the Software, and to
  18. * permit persons to whom the Software is furnished to do so, subject to
  19. * the following conditions:
  20. * The above copyright notice and this permission notice shall be
  21. * included in all copies or substantial portions of the Software.
  22. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  23. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  24. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  25. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  26. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  27. * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  28. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  29. */
  30. package de.polygonal.motor.dynamics.contact;
  31. import de.polygonal.ds.Array2;
  32. import de.polygonal.motor.collision.shape.AbstractShape;
  33. import de.polygonal.motor.collision.shape.ShapeType;
  34. import de.polygonal.motor.dynamics.contact.generator.BoxCircleContact;
  35. import de.polygonal.motor.dynamics.contact.generator.BoxContact;
  36. import de.polygonal.motor.dynamics.contact.generator.BoxPolyContact;
  37. import de.polygonal.motor.dynamics.contact.generator.CircleContact;
  38. import de.polygonal.motor.dynamics.contact.generator.EdgeBoxContact;
  39. import de.polygonal.motor.dynamics.contact.generator.EdgeCircleContact;
  40. import de.polygonal.motor.dynamics.contact.generator.EdgePolyContact;
  41. import de.polygonal.motor.dynamics.contact.generator.PolyCircleContact;
  42. import de.polygonal.motor.dynamics.contact.generator.PolyContact;
  43. import de.polygonal.motor.Settings;
  44. class ContactFactory
  45. {
  46. var _contactMatrix:Array2<ContactRegister>;
  47. var _pool:ContactPool;
  48. var _settings:Settings;
  49. public function new(settings:Settings)
  50. {
  51. _settings = settings;
  52. _pool = new ContactPool(settings);
  53. for (C in
  54. [
  55. CircleContact,
  56. BoxContact,
  57. BoxPolyContact,
  58. PolyContact,
  59. PolyCircleContact
  60. ])
  61. { _pool.registerContactPool(C, settings.contactPoolSize); }
  62. _initializeContactMatrix();
  63. }
  64. public function free():Void
  65. {
  66. for (register in _contactMatrix) register.free();
  67. _contactMatrix.free();
  68. _pool.free();
  69. _contactMatrix = null;
  70. _pool = null;
  71. }
  72. public function create(shape1:AbstractShape, shape2:AbstractShape):Contact
  73. {
  74. var register = _contactMatrix.get(shape1.type, shape2.type);
  75. var contact;
  76. //null contact?
  77. if (register.construct == null)
  78. return null;
  79. if (register.pool == null)
  80. {
  81. //no pool defined; create instance
  82. if (register.primary)
  83. contact = Type.createInstance(register.construct, [_settings]);
  84. else
  85. contact = Type.createInstance(register.construct, [_settings]);
  86. }
  87. else
  88. {
  89. //get object from pool
  90. var pool = register.pool;
  91. if (pool.isEmpty())
  92. {
  93. //pool exhausted; create instance
  94. if (register.primary)
  95. contact = Type.createInstance(register.construct, [_settings]);
  96. else
  97. contact = Type.createInstance(register.construct, [_settings]);
  98. }
  99. else
  100. {
  101. var poolId = pool.next();
  102. contact = pool.get(poolId);
  103. contact.poolId = poolId;
  104. }
  105. }
  106. if (register.primary)
  107. contact.init(shape1, shape2);
  108. else
  109. contact.init(shape2, shape1);
  110. return contact;
  111. }
  112. public function destroy(contact:Contact):Void
  113. {
  114. var poolId = contact.poolId;
  115. if (poolId != Contact.NO_POOL)
  116. {
  117. //recycle contact
  118. var pool = _contactMatrix.get(contact.shape1.type, contact.shape2.type).pool;
  119. pool.put(poolId);
  120. contact.reset();
  121. }
  122. else
  123. {
  124. //destroy contact
  125. contact.free();
  126. }
  127. }
  128. function _initializeContactMatrix():Void
  129. {
  130. _contactMatrix = new Array2<ContactRegister>(5, 5);
  131. _contactMatrix.assign(ContactRegister);
  132. _registerContactHandler(CircleContact , ShapeType.CIRCLE, ShapeType.CIRCLE);
  133. _registerContactHandler(BoxContact , ShapeType.BOX , ShapeType.BOX);
  134. _registerContactHandler(BoxCircleContact , ShapeType.BOX , ShapeType.CIRCLE);
  135. _registerContactHandler(BoxPolyContact , ShapeType.BOX , ShapeType.POLY);
  136. _registerContactHandler(PolyContact , ShapeType.POLY , ShapeType.POLY);
  137. _registerContactHandler(PolyCircleContact, ShapeType.POLY , ShapeType.CIRCLE);
  138. _registerContactHandler(EdgeCircleContact, ShapeType.EDGE , ShapeType.CIRCLE);
  139. _registerContactHandler(EdgeBoxContact , ShapeType.EDGE , ShapeType.BOX);
  140. _registerContactHandler(EdgePolyContact , ShapeType.EDGE , ShapeType.POLY);
  141. }
  142. function _registerContactHandler(C:Class<Contact>, type1:Int, type2:Int):Void
  143. {
  144. _contactMatrix.get(type1, type2).construct = C;
  145. _contactMatrix.get(type1, type2).pool = _pool.get(C);
  146. _contactMatrix.get(type1, type2).primary = true;
  147. if (type1 != type2)
  148. {
  149. _contactMatrix.get(type2, type1).construct = C;
  150. _contactMatrix.get(type2, type1).pool = _pool.get(C);
  151. _contactMatrix.get(type2, type1).primary = false;
  152. }
  153. }
  154. }
  155. import de.polygonal.ds.pooling.ObjectPool;
  156. private class ContactRegister
  157. {
  158. public var construct:Class<Dynamic>;
  159. public var pool:ObjectPool<Contact>;
  160. public var primary:Bool;
  161. public function new() {}
  162. public function free():Void
  163. {
  164. construct = null;
  165. pool = null;
  166. }
  167. }
  168. private class ContactPool
  169. {
  170. var _poolHash:Hash<ObjectPool<Contact>>;
  171. var _args:Array<Dynamic>;
  172. public function new(settings:Settings)
  173. {
  174. _poolHash = new Hash<ObjectPool<Contact>>();
  175. _args = [settings];
  176. }
  177. public function free():Void
  178. {
  179. for (pool in _poolHash)
  180. {
  181. for (contact in pool) contact.free();
  182. pool.free();
  183. }
  184. _poolHash = null;
  185. _args = null;
  186. }
  187. public function get(C:Class<Contact>):ObjectPool<Contact>
  188. {
  189. var key = Type.getClassName(C);
  190. if (_poolHash.exists(key))
  191. return _poolHash.get(key);
  192. else
  193. return null;
  194. }
  195. public function registerContactPool(C:Class<Contact>, size:Int)
  196. {
  197. if (size == 0) return;
  198. var p = new ObjectPool<Contact>(size);
  199. p.allocate(_args[0].lazyPooling, null, function() return Type.createInstance(C, _args), null);
  200. _poolHash.set(Type.getClassName(C), p);
  201. }
  202. }